我得到了以下代码
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
instance Applicative Parser where
pure a = Parser $ \s -> Just (a,s)
f <*> a = Parser $ \s ->
case parse f s of
Just (g,s') -> parse (fmap g a) s'
Nothing -> Nothing
instance Alternative Parser where
empty = Parser $ \s -> Nothing
l <|> r = Parser $ \s -> parse l s <|> parse r s
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where f [] = Nothing
f (x:xs) = if p x then Just (x,xs) else Nothing
ws :: Parser ()
ws = pure () <* many (satisfy isSpace)
我知道ws解析器会删除前导空格。但是我需要一个解释,说明它是如何完成的。我不了解<*
语法(我知道<*>
)。可以帮助我理解语法以及它为什么起作用吗?
没有恐惧!当我们经过小步骤并查看它将我们引向何方时,这很容易。下次,请尝试自己做。
[(<*) = liftA2 const
和(<*) = liftA2 const
,所以
liftA2 f x = (<*>) (fmap f x)
((带有适用性表示法;以了解其用途。在以上链接中也列举了适用性法律。)
所以它执行liftA2 f x = (<*>) (fmap f x)
的操作,除了它返回的计算值始终为ws :: Parser ()
ws = pure () <* many (satisfy isSpace)
= {- (<*) = liftA2 const -}
liftA2 const (pure ()) (many $ satisfy isSpace)
= {- liftA2 f x = (<*>) (fmap f x) -}
fmap const (pure ()) <*> many (satisfy isSpace)
= {- by Applicative laws -}
(pure const <*> pure ()) <*> many (satisfy isSpace)
= {- by homomorphism law of Applicatives -}
pure (const ()) <*> many (satisfy isSpace)
= {- with Applicative Do -}
do { f <- pure (const ())
; r <- many (satisfy isSpace)
; pure (f r) }
=
do { r <- many (satisfy isSpace)
; pure (const () r) }
=
do { _ <- many (satisfy isSpace)
; pure () }
=
do { many (satisfy isSpace)
; pure () }
= {- Monad Comprehension illustration -}
[ () | _ <- many (satisfy isSpace) ]
。
在纯函数中,many (satisfy isSpace)
将完全忽略其第二个参数。我们可以将其称为()
,它不在乎。但是Applicative Functor表示计算,并且f a = ()
在组合之前将众所周知的计算进行组合,因此无论以后是否使用其计算值,每个函数都将得到[[performed。