Inside Parsec


Text.Parsec.Char

satisfy 関数

基本的なパーサの作り方が分かったので、Text.Parsec.Char で定義されているたくさんのパーサの作り方をのぞいてみた。すると、驚いたことに大半が satisfy という関数を使ってパーサを作っていた。satisfy を使っているパーサの一覧を次に示す。
oneOf cs            = satisfy (\c -> elem c cs)
noneOf cs           = satisfy (\c -> not (elem c cs))
space               = satisfy isSpace       <?> "space"
upper               = satisfy isUpper       <?> "uppercase letter"
lower               = satisfy isLower       <?> "lowercase letter"
alphaNum            = satisfy isAlphaNum    <?> "letter or digit"
letter              = satisfy isAlpha       <?> "letter"
digit               = satisfy isDigit       <?> "digit"
hexDigit            = satisfy isHexDigit    <?> "hexadecimal digit"
octDigit            = satisfy isOctDigit    <?> "octal digit"
char c              = satisfy (==c)  <?> show [c]
anyChar             = satisfy (const True)

satisfy のコード

satisfy のコードは次のようになるが、tokenPrim を利用して定義されている。

satisfy f           = tokenPrim (\c -> show [c])
                                (\pos c _cs -> updatePosChar pos c)
                                (\c -> if f c then Just c else Nothing)

satisfy を使う

satisfy は一般のユーザも使用できるので、試してみた。

Prelude> :m Text.Parsec
Prelude Text.Parsec> parseTest (satisfy (< 'd')) "abc"
'a'

letter や digit がブラックボックスでなくなったので、パーサモナドが活用しやすくなった気がしてきた。