Applicativeを使うとParsecが書きやすくなると聞いたのでやってみました。
"(123)"という文字列から、カッコに囲まれた123という値を取り出す処理です。
Applicativeを使わない場合:
import Text.Parsec import Text.Parsec.String parseText :: Parser Int parseText = do value <- between (char '(') (char ')') $ many1 digit return (read value) run :: Show a => Parser a -> String -> IO () run p input = case (parse p "" input) of Left err -> do{ putStr "parse error at " ; print err } Right x -> print x main = do run parseText "(123)"
123
Applicativeを使った場合:
import Text.Parsec import Text.Parsec.String import Control.Applicative parseText :: Parser Int parseText = read <$> (char '(' *> many1 digit <* char ')') run :: Show a => Parser a -> String -> IO () run p input = case (parse p "" input) of Left err -> do{ putStr "parse error at " ; print err } Right x -> print x main = do run parseText "(123)"
123
Applicativeを使うと、doとreturnが消えました。
この程度の規模だと、効果があまりわからないですが、若干短くはなりました。
個人的にはdoを使ったほうが読みやすいですし、書きやすいです。
追記:
Applicativeのbetween使った版。*>の書き方を把握するために、前のバージョンは残しておきます。
import Text.Parsec import Text.Parsec.String import Control.Applicative parseText :: Parser Int parseText = read <$> (between (char '(') (char ')') $ many1 digit) run :: Show a => Parser a -> String -> IO () run p input = case (parse p "" input) of Left err -> do{ putStr "parse error at " ; print err } Right x -> print x main = do run parseText "(123)"
123