2025年9月29日月曜日

Haskell入門 Applicativeスタイル パーサー P251

 既習のモナドを組み合わせると、パーサーもこんなふうになるというよい例だと思います。ただ、かなり複雑にはなってきていますが。 20170401のような日付のパーサーの例です。

data YMD = YMD Int Int Int deriving Show    
countRead :: Read a => Int -> Parser Char -> Parser a
countRead i = fmap read . count  i  
ymdParser :: Parser  YMD                                                                    
ymdParser = YMD <$> countRead 4 digit <*> countRead 2 digit <*> countRead 2 digit 

1. YMD は関数:データコンストラクタ YMD は、単なる値ではなく
 YMD :: Int -> Int -> Int -> YMD という「Intを3つ受け取って YMD を返す関数」でもある。
2. countRead の役割:countRead n digit は「数字を n 個読み取り、それを整数として解釈する」パーサーである。
 例えば: countRead 4 digit :: Parser Int(年を読む)
      countRead 2 digit :: Parser Int(月や日を読む)
3. <$> で最初の適用:(<$>) :: (a -> b) -> Parser a -> Parser b
 a = Int  b = Int -> Int -> YMD  関数 f = YMD 値 Parser a = countRead 4 digit
 したがって:  YMD <$> countRead 4 digit :: Parser (Int -> Int -> YMD)
 ここで、Parser の中には「年をすでに受け取った部分適用関数 YMD y」が入っている。
4. <*> で次々に引数を渡す:次の <*> により
  Parser (Int -> Int -> YMD) <*> Parser Int :: Parser (Int -> YMD)
  さらにもう一度 <*> を使うと:
  Parser (Int -> YMD) <*> Parser Int ::  Parser YMD
※イメージ表せば
 <$>:外の関数を箱に入れる    <*>:箱の中の関数に箱の中の値を渡す 

0 件のコメント:

コメントを投稿