fail
Monad中的方法被一些人认为是一个坑;这是对类的任意添加,而不是来自原始的范畴理论。当然,在当前的情况下,许多Monad类型具有逻辑和有用性fail
实例。
MonadPlus类是Monad的子类,它提供了mzero
方法,该方法逻辑地将失败的概念封装在一个单一的单元中。
因此,一个库设计人员如果想要编写一些执行某种故障处理的一元代码,可以选择让他的代码使用fail
方法,或者将其代码限制在MonadPlus类中,这样他就可以对使用mzero
即使他不关心单性组合mplus
完全是行动。
关于这个主题的一些讨论在这个wiki页面中关于改革MonadPlus课程的建议。
所以我想我有一个具体的问题:
如果有的话,哪一个单一的例子有一个自然的fail
方法,但不能是MonadPlus的实例,因为它们没有逻辑实现mplus
?
为了简化monad的使用,并使抽象出monad的用法更容易,他们引入了do
。例如,此代码:
do putStr "What's your full name? "
[name,surname] <- getLine >>= return . words
putStr "How old are you? "
age <- getLine >>= return . read
if age >= 18
then putStrLn $ "Hello Mr / Ms " ++ surname
else putStrLn $ "Hello " ++ name
翻译为:
putStr "What's your full name? " >>
getLine >>= return . words >>= \[name,surname] ->
putSr "How old are you? " >>
getLine >>= return . read >>= \age ->
if age >= 18
then putStrLn $ "Hello Mr / Ms " ++ surname
else putStrLn $ "Hello " ++ name
fail
,在不匹配的情况下调用:
putStr "What's your full name? " >> let
helper1 [name,surname] =
putSr "How old are you? " >> let
helper2 age =
if age >= 18
then putStrLn $ "Hello Mr / Ms " ++ surname
else putStrLn $ "Hello " ++ name
helper2 _ = fail "..."
in getLine >>= return . read >>= helper2
helper1 _ = fail "..."
in getLine >>= return . words >>= helper1
Either
它是一元实例,如下所示:
{-# LANGUAGE FlexibleInstances #-}
instance Monad (Either String) where
(Left x) >>= _ = Left x
(Right a) >>= f = f a
return = Right
fail = Left
每一个实例mplus
应符合这两条法律:
mzero `mplus` a -> a
a `mplus` mzero -> a
合理的MonadPlus
例如:
instance MonadPlus (Either a) where
mzero = Left undefined
mplus (Left _) b = b
mplus a _ = a
mplus
返回第二次计算。注意它与(>>)
它不符合法律:
Left a >> Right b -> Left a
Left a `mplus` Right b -> Right b
(>>)
将在第一次计算时停止,而mplus
而是尝试三。[]
也有这样的行为:
[] >> [1..4] -> []
[] `mplus` [1..4] -> [1,2,3,4]
这只是为了讨论MonadPlus
特别是mplus
与(>>)
形成对比
相似问题