data CI = CI Int Int
给定一个表示复数的数据类型,我想为 CI 构建一个解析器,它可以转换"a"
为CI a 0
和。例如,我想要一个返回值的函数(理想情况下,类似的东西也可以)。我还想让 CI 成为."(a,b)"
CI a b
parseCI
runParser parseCI "(1,2)"
[(CI 1 2, "")]
read
我想使用下面代码中的函数和定义来做到这一点(基本上,没有任何先进的东西,比如 Parsec),但我不知道从哪里开始。一些让我走上正轨的起始代码和/或提示会很有帮助。我不是在寻找完整的答案,因为我想自己弄清楚。
module Parser where
import Control.Applicative
import Control.Monad
newtype Parser a = Parser { runParser :: String -> [(a,String)] }
satisfy :: (Char -> Bool) -> Parser Char
satisfy f = Parser $ \s -> case s of
[] -> []
a:as -> [(a,as) | f a]
char :: Char -> Parser Char
char = satisfy . (==)
string :: String -> Parser String
string str = Parser $ \s -> [(t,u) | let (t,u) = splitAt (length str) s, str == t]
instance Functor Parser where
fmap f p = Parser $ \s ->
[ (f a,t)
| (a,t) <- runParser p s
]
instance Applicative Parser where
pure a = Parser $ \s -> [(a,s)]
af <*> aa = Parser $ \s ->
[ (f a,u)
| (f,t) <- runParser af s
, (a,u) <- runParser aa t
]
instance Alternative Parser where
empty = Parser $ \s -> []
p1 <|> p2 = Parser $ (++) <$> runParser p1 <*> runParser p2`
instance Monad Parser where
return = pure
ma >>= f = Parser $ \s ->
[ (b,u)
| (a,t) <- runParser ma s
, (b,u) <- runParser (f a) t
]
instance MonadPlus Parser where
mzero = empty
mplus = (<|>)