5

私は Parsec を学習しようとしており、単純な電子メール アドレスを解析しようとしています。次のコードを試しました。私の予想される出力は、文字列としての電子メール アドレス全体です。しかし、コードを実行すると、「.com」しか表示されません。何が起こっているのか教えてもらえますか?

{-# LANGUAGE NoMonomorphismRestriction #-}

import Text.Parsec
import Control.Applicative hiding ((<|>))

email = many1 alphaNum
     *> char '@'
     *> many1 alphaNum
     *> string ".com"

emailstr = parse email "" "xxxx@yyy.com"
4

1 に答える 1

12

の型シグネチャは、 2 番目のパーサー*>からの結果を返し、最初のパーサーからの結果を破棄することを示しています。したがって、シーケンスの最後のパーサーからの結果のみを返します。email

おそらくあなたが望むのは、もっと似たものです

email =
  stitch
    <$> many1 alphaNum
    <*> char '@'
    <*> many1 alphaNum
    <*> string ".com"

これにより、4 つのパーサーが実行され、それぞれの結果が引数として に渡されstitchます。の適切な実装を作成する場合stitch:

stitch a b c d = a ++ [b] ++ c ++ d

次に、文字列を取り戻す必要があります。

この時点で、ユーザー名とドメインをデータ構造などの別のフィールドに入れることもできることに注意してください。

data Email = Email {username, domain :: String}

email =
  Email
    <$> many1 alphaNum
    <*  char '@'
    <*> ((++) <$> many1 alphaNum <*> string ".com")

これで、パーサーはEmail単なる文字列ではなく構造体を返します。これはあなたが求めているものではないかもしれませんが、より洗練されたパーサーを作成する方法を示しています。

Applicativeこれらはすべて、一般的に優れたスタイルと見なされている Parsec へのインターフェイスを使用しています。Parsec を使用するもう 1 つの方法は、次のMonadインターフェイスです。

email = do
  a <- many1 alphaNum
  b <- char '@'
  c <- many1 alphaNum
  d <- string ".com"
  return (a ++ [b] ++ c ++ d)
于 2013-08-18T09:01:02.820 に答える