Haskell Parsec遇到了麻烦

Jay*_*Jay 5 haskell parsec

我正在尝试学习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"
Run Code Online (Sandbox Code Playgroud)

Mat*_*hid 12

声明的类型签名*>返回第二个解析器的结果,并从第一个解析器中抛出结果.因此,email仅返回序列中最终解析器的结果.

你可能想要的更像是什么

email =
  stitch
    <$> many1 alphaNum
    <*> char '@'
    <*> many1 alphaNum
    <*> string ".com"
Run Code Online (Sandbox Code Playgroud)

这将运行四个解析器并将每个解析器的结果作为参数传递给stitch.如果您为以下内容编写合适的实现stitch:

stitch a b c d = a ++ [b] ++ c ++ d
Run Code Online (Sandbox Code Playgroud)

然后你应该找回你的字符串.

请注意,此时,您还可以将用户名和域放入数据结构的单独字段中:

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

email =
  Email
    <$> many1 alphaNum
    <*  char '@'
    <*> ((++) <$> many1 alphaNum <*> string ".com")
Run Code Online (Sandbox Code Playgroud)

现在你的解析器返回一个Email结构,而不仅仅是一个普通的字符串.这可能不是你想要的,但它演示了如何编写更复杂的解析器.

所有这些都是使用ApplicativeParsec 的界面,这通常被认为是好的风格.使用Parsec 的一种方法是Monad界面:

email = do
  a <- many1 alphaNum
  b <- char '@'
  c <- many1 alphaNum
  d <- string ".com"
  return (a ++ [b] ++ c ++ d)
Run Code Online (Sandbox Code Playgroud)