すごいH本3

7章まで読んだ。7章が特別分厚いのかと思ったら今後はこんな重さばっかりらしい…

読んでてへぇとなったとことか疑問に思ったとこのメモ
・foldlがリストを右から評価してるように見えた話、Data.Listにはちゃんと(?)左から評価するfoldl'があるらしい。
・(連想)リストのインデント、今までカンマは前の要素につけてたけど、この本みたいに[と,と]を揃える書き方が主流なんかな。
・リストに対する再帰だ!畳み込みつかったろ!とはなれんな…foldが馴染む気がしない…

Data.Map.fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Data.Map.Internal.Map k a

なので結合関数で型が変わるようなことはできない(文字列を連結とかはできる)。キーが同じ値をリストにまとめたいときは、あらかじめ値をリストにくるんでおく必要がある。
特に意味のない例:

testMap = Data.Map.fromListWith (++) $ map (\(k, v) -> (k, [v])) [(Nothing, "HAHAHA")
                                                                                                       ,(Just 1, "ONE")
                                                                                                       ,(Just 1, "ICHI")
                                                                                                       ]

・データ型作れる場合と作れない場合の違いがあまりわからなかった。

-- だめ
data Bit = 0 | 1
data AB = 'a' | 'b'
data AB = a | b
-- できる
data Bool = False | True
data AB = A | B
data BC = B | C -- ABと同時にはできない

右辺の値(コンストラクタ)は大文字からじゃないとだめそう。本文のNumの定義を見るにBitはできてもよさそうだが…
値コンストラクタはフィールドを引数にして宣言したデータ型を返す関数らしいので名前は早いもの順で被ったらだめそう?けどBoolは(値を実際に使おうとしたら即エラーでたけど少なくともコンパイルは)できたのよね…
・データ宣言には型制約をつけない。確かに宣言するときはその制約使ってないか。
・(多相化した)型シノニム、#defineをイメージしたらよさそう。
・ロッカーの暗証番号を真似してパスワード管理できそうって変数名だけ変えてみた。冷静に考えると、ロッカーなら番号が存在してそのあと空いてるかどうかってあるけど、サービス登録ってしてるかしてないかしかないから微妙に対応してなかった。
・フィールドに文字列を持つデータ型を宣言すると

data SMaybe = SNothing | SJust String deriving (Show)
show SNothing -- "SNothing"
show (SJust "abc") -- "SJust \"abc\""

みたいにshowしたときごみがひっつくのどうにかできないのかな。
・値コンストラクタを中置関数にするときはコロンから始めないといけないが、値コンストラクタでない関数は先頭にコロンをつけてはいけない。
・二分探索木の表示を本のようにインデントそろえて見やすくしようと手動でShowのインスタンス宣言をしたけどきれいにそろえることができなかった(何なら余計見にくくなった)。

instance (Show a) => Show (Tree a) where
    show EmptyTree = "_"
    show (Node x left right) = "Node: " ++ show x ++ "\nLeft: " ++ show left ++ ", Right: " ++ show right
numTree = foldr treeInsert EmptyTree [8,6,4,1,7,3,5]
--numTree = 
--Node: 5
--Left: Node: 3
--Left: Node: 1
--Left: _, Right: _, Right: Node: 4
--Left: _, Right: _, Right: Node: 7
--Left: Node: 6
--Left: _, Right: _, Right: Node: 8
--Left: _, Right: _

こんなはずじゃ…
・上のやつで、インスタンス宣言に型クラス制約が必要なのしばらくわからず苦しんだ。確かにその条件使うけど…
サブクラス化でも型クラス制約出てきたし、まあ必要なら使う、データ宣言時は必要じゃないから禁止ってことか。
・Eqの定義、¬(x /= y) -> (x = y)だけ言えば¬(x = y) -> (x /= y)は対偶だから言わなくていい気がしたけど、==と/=はすでに定義された関係記号じゃなくてまだ定義されてない演算子なのね。
・where節本当によく出てくるな。ここまで出てきたのは関数内の変数の束縛、モジュール宣言、インスタンス宣言、サブクラス化かな。
・本ではNumはEqのサブクラスって書いてたけど、

:i Num
class Num a where
  (+) :: a -> a -> a
-- 以下略

ってなってて、(==)が定義されてなかったので混乱してる。確かにこれなら(Num a, Eq a) =>...って両方書く必要あるのわかるけど。
・FunctorのインスタンスとしてのEitherはただのちょっと高級なMaybeみたいに感じる。
・ファンクタのカインドよくわからん。

:i Functor
class Functor (f :: * -> *) where
...
:k Functor
Functor :: (* -> *) -> Constraint
:k Num
Num :: * -> Constraint

これを見ると型クラスのカインドは(インスタンスのカインド)-> Constraintって形みたい。Constraintって何でしょ。
ファンクタのインスタンスは型引数を1つとる型コンストラクタなんかな。文中「友達になりたい」の意味がわからん…

知らないことが増えてきたので書くことが多い。このまま増えたらそのうち本まるまる写すことになりそうw
ところで代数的データ型ってどの辺が代数的なの?