ふつうのHaskell本読了

「ふつうのHaskellプログラミング」(青木峰郎著)を一通り読んだ。関数、型クラスあたりの話が非常におもしろい。Haskellの関数って引数が2つ以上あるように見えても、それは実は引数を1つ取って関数を返す高階関数なんだという話とか、関数定義のところで引数をかかずに関数だけで関数を定義するポイントフリースタイルの話とか、なるほどなーと思った。話が妙にすっきりしてる。

例えば、以下のようにtakeの型は本来 Int -> [a] -> [a] だけど、Intに当たる部分に3を適用したt3の型は [a] -> [a] になっている。

% ghci
GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude> :t take
take :: Int -> [a] -> [a]
Prelude> let t3 = take 3
Prelude> t3 [1..]
[1,2,3]
Prelude> t3 [x*x|x <- [1..]]
[1,4,9]
Prelude> :t t3
t3 :: [a] -> [a]
Prelude>
Prelude> let primes = sieve [2..] where sieve (p:xs) = p : sieve [x| x<-xs, mod x p /= 0]
Prelude> t3 primes
[2,3,5]
Prelude> t3 $ drop 10 primes 
[31,37,41]
Prelude> 

型クラスはRubyのmix-inともどっか通じるものを感じるけど、多面体を上から見るのと横から見るぐらいの違いがあるような気がする。Haskellの型クラスにあるクラスメソッドって、Rubyだとmix-inのためにクラスに実装しないといけないメソッドに相当してる。mix-inは多重継承を禁止しつつスーパークラス以外のクラス(モジュール)からも実装だけ継承できる仕組みで、これはすごい交通整理法だと思ったけど、Hakellの型クラスの継承を使うと、実はmix-in以上に柔軟な実装の共有ができるんじゃないのかしらと思った。って、書いてて意味が分からなくなった。

ポリモーフィズムが動的型付けとはそれほど密接に関わってるわけでもないってことも、分かった。Haskellの多相型と、JavaジェネリクスC++のテンプレートって似てるのかな、どう違うんだろう。

モナドは、かなりモヤモヤ。定義は明確だけどモナド則が読み下せない。上っ面を読み進めているうちに記号の意味を忘れたりしてて、定義を示されても「あれ、どう読むんだっけ?」という感じ。こんなところもHaskellは数学っぽいような感じ。

モナドのことを「関数をつなぐ」と説明しているけど、つなぐというと関数の合成を思い浮かべて、はてなという感じ。もしかして、モナドの本質って「分ける」ほうじゃないのかしら。関数を並べて合成するとそれは関数でしかなく、関数である以上、値を入れたら何か一意に決まった値が出てくる。世界は変わらない。時間もない。スタティックな計算処理。でも実際には入れる値によって適用する関数を変えるように分岐したり、世界に副作用を及ぼす前と後を分けたいというニーズがある。それをやるのがモナドを使って関数を並べる意味かしら。あ、それを副作用と呼ぶだけのことか。うーん。

とか、意味論とか解釈論的なことって空回りな感じ。いろいろ実際のコードを読み書きすると、きっと見えてくるものがあって、モヤモヤは解消していくものなんだろうな。

Wiki実装の最終章は、かなり読み飛ばし。パーサーコンビネーターって初めて知った。そんな便利なものが世の中にあるのかと思った。