我正在阅读a revealing example of using a bind operator:
Just 5 >>= (\ x -> if (x == 0) then fail "zero" else Just (x + 1) )
返回Just 6
。
我对fail
的行为及其在示例中的有用性感到困惑。
在查看代码时,我认为fail "zero"
可能具有以下含义:
然后我意识到,在进行类型内聚后,异常变为Nothing
(记录在here中)。令我感到困惑的是,没有类型强制实施fail
只是程序中的错误。
Prelude> fail "zero" :: Maybe Int
Nothing
Prelude> fail "abc" :: [Int]
[]
Prelude> fail "zero"
*** Exception: user error (zero)
在这个示例中,我的问题是关于fail "zero"
的有效性。
对(\ x -> if (x == 0) then fail "zero" else Just (x + 1) )
函数的简单理解是对a -> Maybe a
的简单尝试吗?
如果只需要图解(\ x -> if (x == 0) then Nothing else Just (x + 1) )
,是什么使我们无法使用a -> Maybe a
?
我在下面发现此版本的方法更容易,更轻松地掌握了相同的示例。
Prelude> g x = if (x == 0) then Nothing else Just (x + 1)
Prelude> Just 0 >>= g
Nothing
Prelude> Just 1 >>= g
Just 2
答案 0 :(得分:6)
对于
(\ x -> if (x == 0) then fail "zero" else Just (x + 1) )
函数来说,a -> Maybe a
的读法是否是简单的案例?
是的
如果只需要图解
(\ x -> if (x == 0) then Nothing else Just (x + 1) )
,是什么使我们无法使用a -> Maybe a
?
没事。
答案 1 :(得分:4)
要详细说明Daniel的完全正确答案,fail
是MonadFail
类型类中的一个函数。它最初属于Monad
类型类,但实际上并没有属于其中,因为某些Monad
并没有失败的概念。对于确实具有失败概念的用户,fail
的类型为MonadFail m => String -> m a
。也就是说,对于实现了MonadFail
接口的任何类型以及任何类型的a
,fail
都可以采用字符串并产生由a
参数化的该类型的实例。 / p>
对于Maybe a
,fail s = Nothing
。
对于[a]
,fail s = []
。
对于IO a
,fail
引发包含字符串的异常。
许多人为MonadFail
之类的类型Either String a
编写fail s = Left s
的实例。它不属于标准库的主要原因是因为Either
是一种相当抽象的类型,尽管将Right
视为成功而将Left
视为失败是很常见的,但可以合理地用作Monad
,但语义已翻转。 (例如,如果您想尝试N件事,而如果一件事情失败了,则继续进行下一件事情,但是取得第一个结果,那么您需要使用Left
作为成功案例。)
编辑:
此外,当您编写类似的代码
时do
Just y <- getMaybe x
return y
这不合时宜:
do
case getMaybe x of
Just y -> return y
_ -> fail "Failed pattern match"
这意味着失败的模式匹配将在IO a
中引发异常,但在[a]
中为空列表,而在Nothing
中为Maybe a
。 / p>