我有这个单子对象。
data Parser a = Parser (String -> Maybe (a, String))
instance Functor Parser where
-- fmap :: (a -> b) -> Parser a -> Parser b
fmap f (Parser pa) = Parser $ \input -> case pa input of
Nothing -> Nothing
Just (a, rest) -> Just (f a, rest)
instance Applicative Parser where
pure = return
(<*>) = ap
instance Monad Parser where
--return :: a -> Parser a
return a = Parser $ \input -> Just (a, input)
--(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(Parser pa) >>= f = Parser $ \input -> case pa input of
Nothing -> Nothing
Just (a,rest) -> parse (f a) rest
我对item
的定义是这样的,我被告知“读入一个字符”,但我没有真正看到任何读物。
item :: Parser Char
item = Parser $ \ input -> case input of "" -> Nothing
(h:t) -> Just (h, t)
但是,好的,也许我应该放松一下如何将“ read”和jibe一词带入其中。继续,我有
failParse :: Parser a
failParse = Parser $ \ input -> Nothing
sat :: (Char -> Bool) -> Parser Char
sat p = do c <- item
if p c
then return c
else failParse
这就是我很困惑的地方。变量c
中存储了什么?由于item
是带有参数Parser
的{{1}},因此我的第一个猜测是Char
正在存储这样的对象。但是,经过一秒钟的思考,我知道do表示法现在不起作用了,您没有得到monad,而是得到了monad的内容。很好,但这告诉我c
是函数
c
但是显然,这是错误的,因为\ input -> case input of "" -> Nothing
(h:t) -> Just (h, t)
定义的下一行将sat
视为字符。这不仅不是我所期望的,而且还比我期望的低了三个层次!它不是函数,不是Maybe对象,也不是元组,而是埋在函数内部的Just元组的左坐标!这个小人物在外面如何一直工作?指示c
提取Monad的这一部分的内容是什么?
答案 0 :(得分:3)
如评论所述,<-
只是do notation语法糖,等效于:
item >>= (\c->if p c
then return c
else failParse)
好的,让我们看看c
是什么?考虑(>>=)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
或更可读的方式:
Parser a >>= (a -> Parser b)
现在,将其与上面的表达式item >>= (\c->if p c then return c else failParse)
匹配:
Parer a = item
和
(a->Parser b) = (\c->if p c then return c else failParse)
和item
的类型为:
item :: Parser Char
因此,我们现在可以将a
中的(>>=)
替换为Char,给出
Parser Char >>= (Char -> Parser b)
现在\c->if p c then return c else failParse
的类型也为:(Char -> Parser b)
所以c
是一个Char,整个表达式可以扩展为:
sat p =
item >>= (\c->...) =
Parser pa >= (\c->...) = Parser $ \input -> case pa input of
Nothing -> Nothing
Just (a,rest) -> parse (f a) rest
where f c = if p c
then return c
else failParse
pa input = case input of "" -> Nothing
(h:t) -> Just (h, t)
答案 1 :(得分:1)
TL; DR:通常,根据Monad法,
do { item }
与
相同do { c <- item
; return c
}
从某种意义上说,它是由return
定义的。详细信息如下。
它确实从正在被“ read” 的输入字符串中取出一个字符,因此从这个意义上来说,它会“ reads” 该字符:
item :: Parser Char
item = Parser $ \ input -> -- input :: [Char]
case input of { "" -> Nothing
; (h:t) -> Just (h, t) -- (h:t) :: [Char]
} -- h :: Char t :: [Char]
我敢肯定有一个定义
parse (Parser pa) input = pa input
在某处定义;所以
parse item input = case input of { "" -> Nothing ; (h:t) -> Just (h, t) }
接下来,(>>=)
是什么意思?这意味着
parse (Parser pa >>= f) input = case (parse (Parser pa) input) of
Nothing -> Nothing
Just (a, leftovers) -> parse (f a) leftovers
即
parse (item >>= f) input = case (parse item input) of
Nothing -> Nothing
Just (a, leftovers) -> parse (f a) leftovers
= case (case input of { "" -> Nothing ; (h:t) -> Just (h, t) }) of
Nothing -> Nothing
Just (a, leftovers) -> parse (f a) leftovers
= case input of
"" -> Nothing
(h:t) -> case Just (h, t) of {
Just (a, leftovers) -> parse (f a) leftovers }
= case input of
"" -> Nothing
(h:t) -> parse (f h) t
现在
-- sat p: a "satisfies `p`" parser
sat :: (Char -> Bool) -> Parser Char
sat p = do { c <- item -- sat p :: Parser Char
; if p c -- item :: Parser Char, c :: Char
then return c -- return c :: Parser Char
else failParse -- failParse :: Parser Char
}
= item >>= (\ c ->
if p c then return c else failParse)
(通过展开do
语法),等等
parse (sat p) input
= parse (item >>= (\ c ->
if p c then return c else failParse)) input
-- parse (item >>= f) input
-- = case input of { "" -> Nothing ; (h:t) -> parse (f h) t }
= case input of
"" -> Nothing
(h:t) -> parse ((\ c -> if p c then (return c)
else failParse) h) t
= case input of
"" -> Nothing
(c:t) -> parse (if p c then (return c)
else failParse) t
= case input of
"" -> Nothing
(c:t) -> if p c then parse (return c) t
else parse failParse t
= case input of
"" -> Nothing
(c:t) -> if p c then Just (c, t)
else Nothing
现在sat p
的含义应该很清楚:对于c
产生的item
(如果输入为非空,则是输入中的第一个字符),如果{{ 1}}成立,p c
被接受并且解析成功,否则解析失败:
c