プログラミング Haskell 第8章 関数型パーサー その2
前回はパーサーを連結する演算子の導入したところまででした。
- 連結演算子で構築するパーサの典型的な形はこんな感じ。lambda をくくるかっこは不要ですが、わたしにとってはまだあったほうがわかりやすいのでくくっています。
p1 >>= (\v1 -> p2 >>= (\v2 -> ... pn >>= (\vn -> return (f v1 v2 ... vn))..)
-
- モナドですね
- そしてこれと同じ内容を記述するために do 記法があります
do v1 <- p1 v2 <- p2 ... vn <- pn return (f v1 v2 ... vn)
-
- vi <- pi のような式は生成器と呼ぶ(リスト内包表記と同じ)
- 値が必要ないなら vi <- pi のかわりに pi だけでもいい
ふつうの Haskell プログラミングでももちろん do 記法の説明は読みましたが、今回すとんと腑に落ちました。その間に lambda calculus のことを少し調べる機会があったのでそのおかげのような気がします。個人的に「なるほど」と思ったポイントは
- v <- p の記法はあたかも代入のように見えるし、そのように見せることでとっつきやすい表現にしているのでしょうが、これは単に lambda の引数 v を束縛しているだけ。
- do 記法はどんどん lambda (関数)がネストしている。つまりパースする関数を連結しているんじゃなくて、パーサを作る関数を繋げていっている感じ
モナド難しいとよく言われますが、今回とてもしっくりと頭に入ってきて、いやそんなことないんじゃないかなと思いました。わかるまではなんだか難しいことを言ってるような気がするけど、わかってみるとなーんだそんなことなのか、と。けどそれを説明しようと思うとやっぱり難しい。難しいと言われるものってそんなものですよね。
do 記法についての部分がわかって嬉しかったので、ちょっとパーサーの内容からずれてしまいました。明日からまたパーサーを組み合せる他の方法に進んでいきます。