の写経の続きです。
sepBy と sepBy1
「パーサによって区切られるパーサの列をパースします」って分かりにくい説明が書かれていますが、動かしてみます。
import Text.ParserCombinators.Parsec tstSepBy :: String -> [String] tstSepBy str = case parse strToNumList "" str of Left err -> [] Right n -> n -- "123,456, 789" --=> ["123","456","789"] strToNumList :: Parser [String] strToNumList = sepBy1 number separator -- 数字:'0'-'9' が1個以上 number :: Parser String number = many1 digit -- 区切りの定義:スペースか ',' が1個以上 separator :: Parser () separator = skipMany1 (space <|> char ',')
指定された区切りで分割してリストにして返す、ってことのようです。
*Main> tstSepBy "123,456,789" --=> ["123","456","789"] *Main> tstSepBy "123,456 ,,, , 789" --=> ["123","456","789"] -- リストになればこっちのもの。やりたい放題。 *Main> foldr (\x y->((read x)::Int)+y) 0 $ tstSepBy "123,456,789" --=> 1368
sepEndBy と sepEndBy1
区切り文字、終端文字の両方として認識します。
strToNumList :: Parser [String] strToNumList = sepEndBy1 number separator
*Main> tstSepBy "123,456,789" --=> ["123","456","789"] *Main> tstSepBy "123,456,789," --=> ["123","456","789"] *Main> tstSepBy "123,456,789,dddddddddddddddddddddd" --=> ["123","456","789"] *Main> tstSepBy "123,456,789, Hello" --=> ["123","456","789"]
satisfy
satisfy は 関数 f を引数に取り、f を適用して True となる文字を返す。
satisfy :: (Char -> Bool) -> CharParser st Char -- isDigit が True を返す文字をパースする。 digit = satisfy isDigit -- (\c -> c `elem` cs) が True を返す文字(csの中にに含まれている) -- をパースする。 oneOf cs = satisfy (\c -> c `elem` cs)