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

的类型签名*>表示它返回来自第二个解析器的结果,并丢弃来自第一个解析器的结果。因此,email仅返回序列中最终解析器的结果。

你可能想要的是更像

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

这将运行四个解析器并将每个解析器的结果作为参数传递给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结构,而不仅仅是一个纯字符串。这可能不是您所追求的,但它演示了如何编写更复杂的解析器。

所有这些都是使用ApplicativeParsec 的接口,这通常被认为是好的风格。使用 Parsec的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 回答