ふつける:11章読んでる
読み終わってはいません.11章は,ふつけるの言葉を借りるのならば"Haskell最大の難関".C言語でのポインタ,Perlでのオブジェクト指向,Pythonでのインデント,Rubyでのドキュメント作成*1みたいなもんですか.
Monadを理解する事で,Haskellerになれる事を信じて.
とりあえず少しずつ理解していくのが大事だと思う.えっと,まず,Monadには演算を繋ぐ,という目的があるのね.
Monadクラス
Monadクラスって何?クラス定義の中心は,これ,とのこと.
class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a
(>>=)*2はbindと読むそうです.なるほど,繋いでる感じなんだな.
正しいモナドであるためには,この2つのクラスメソッドを実装している必要があります.
モナド則
モナドの定義(なんだと思う).
Haskellにおいてモナドとは,Monadクラスのインスタンスであり,そのクラスメソッドの(>>=)とreturnを正しく実装し,モナド則を満たす型の事である.
モナド則とは?
- (return x) >>= f == f x
- m >>= return == m
- (m >>= f) >>= g == m >>= (\x -> f x >>= g)
今はまだ理解しなくて良いのね.感じるぞ.・・・だめだ,感じれねい.
Maybeモナド
以前,lookupの動きを試していた時に,ボクはもうモナドに出会っていたのですね*3.
Maybeは,モナドとして使った時に真価を発揮する.lookup関数を繰り返し使って検索する時に便利,とのこと.
ふつけるに書いてある事を,10周年にかこつけてエヴァっぽくすると,こうなる.
例えば,こういうタプルのリストがあるとする.
children = [ ("1st", [("name","Rei"),("evangelion","zero")]), ("2nd", [("name","Asuka"),("evangelion", "2nd"),("mother","Kyoko")]), ("3rd", [("name","Shinji"),("evangelion","1st"),("mother","Yui")]) ]
ここで,3rd childrenの母親(mother)の名前は?となると,
case (lookup "3rd" children) of Just entries -> lookup "mother" entries Nothing -> Nothing
とする事で得られる.まず"3rd"を検索し,次に"mother"を検索している.これを,
- まず"3rd"を検索し,次に"mother"を検索する
- ただし,はじめの検索が失敗したら次の検索はしなくてもよい
とできるのが,Maybeモナド.
Maybeモナドとして使うと,さっきの式と同じ式が,たった一行でできる.簡単に書けるし,(意味さえ分かっていれば)読み易い.
lookup "3rd" children >>= lookup "mother"
(>>=)が出てきた.実際にやってみよう.
Main> lookup "1st" children >>= lookup "mother" Nothing Main> lookup "3rd" children >>= lookup "mother" Just "Yui" Main> lookup "4th" children >>= lookup "mother" Nothing
return?
よくわからないreturn.同じように,ふつけるではreturnも使っているのだけども,その使い方はこんな感じのようだ.
(return children >>= lookup "2nd") >>= lookup "evangelion"
ふつけるにすげぇ分かり易い説明が書いてあるんだけど,return childrenはMaybe aで,lookup "2nd"はa -> Maybe aになり,結果括弧内はMaybe aになる.そんで,同じようにlookup "evengelion"はa -> Maybe aなので,式全体を通すと,Maybe aになる.
ここでもう一度,returnの型の定義を見よう.
return :: a -> m a
だ.returnのaにchildrenが当てはまり,Maybe aを返してる事になる.凄いな.
実際に型を確認すると,
Main> :t return children return children :: Monad a => a [([Char],[([Char],[Char])])] -- このaはMaybeだと思えば良い Main> :t lookup "2nd" lookup "2nd" :: [([Char],a)] -> Maybe a Main> :t (return children >>= lookup "2nd") return children >>= lookup "2nd" :: Maybe [([Char],[Char])] Main> :t lookup "evengelion" lookup "evengelion" :: [([Char],a)] -> Maybe a Main> :t (return children >>= lookup "2nd") >>= lookup "evangelion" return children >>= lookup "2nd" >>= lookup "evangelion" :: Maybe [Char]
なるほどなぁ.
ここでもう一度,(>>=)を思い出そう.(>>=)の型の定義は,
(>>=) :: m a -> (a -> m a) -> m b
だ.Maybe aが左辺にあって,a -> Maybe aがまさに右辺にあり,Maybe bが返ってるではないか!
つ,つぎはリストモナドね.