Parsec 入門


Parsec で do を使わない方法

do 記法は審美的に問題

Parsecでパーサを使ったパターン定義に Applicative を使ってその簡潔な記述法に慣れてしまうと、do 記法を使うのが嫌になってきた。たとえば Applicative で記述したつぎのようなパターンを、

Prelude Text.Parsec> parseTest (char '(' *> many letter <* char ')')
 "(hello)"
"hello"

do 記法で記述すると次のようになって審美的にも好ましくない。

Prelude Text.Parsec> parseTest (do char '('; x <- many letter; char ')';
 return x)
 "(hello)"
"hello"

しかし、パターンの連接は do 記法でないと書けない。

Prelude Text.Parsec> parseTest (do string "foo"; string "bar") "foobar"
"bar"

do 記法を使わない方法

しかし、幸いなことに Parsec のパーサーモナドはモナド値を次のモナドで利用することはあまりない。したがって do ... ; ... の代わりにモナド演算子の >> を使うことができる。このやり方だと上のパターンは、string "foo" >> stirng "bar" と書けて、余分な do 記法がいらない。
Prelude Text.Parsec> parseTest (string "foo" >> string "bar") "foobar"
"bar"

>> 演算子で連結したパーサは many などのパーサコンビネータの引数にすることもできる。

Prelude Text.Parsec> parseTest (many (string "foo" >> string "bar"))
 "foobarfoobar"
["bar","bar"]

しかし、次のように前後のパターンにマッチした文字列を結合して戻り値にしたいときは do 記法がいる。

Prelude Text.Parsec> parseTest (do x <- string "foo"; y <- string "bar"; 
return (x++y)) "foobar"
"foobar"

しかし、これは Applicative を使えば次のように書ける。

Prelude Text.Parsec> parseTest ((++) <$> string "foo" <*> string "bar")
 "foobar"
"foobar"

Applicative と >> モナド演算子のおかげで、Parsec のパターン記述に do 記法と return を極力使わないで済みそうだ。