我正在尝试学习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"
答案 0 :(得分: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
结构,而不仅仅是一个纯字符串。这可能不是你想要的,但它演示了如何编写更复杂的解析器。
所有这一切都使用了Parsec的Applicative
接口,这通常被认为是好的风格。使用Parsec的其他方式是Monad
接口:
email = do
a <- many1 alphaNum
b <- char '@'
c <- many1 alphaNum
d <- string ".com"
return (a ++ [b] ++ c ++ d)