失败“零”是在简单的“ a->也许是a”示例中不生成任何内容的一种方式

时间:2019-05-17 18:26:49

标签: haskell monads

我正在阅读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

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的完全正确答案,failMonadFail类型类中的一个函数。它最初属于Monad类型类,但实际上并没有属于其中,因为某些Monad并没有失败的概念。对于确实具有失败概念的用户,fail的类型为MonadFail m => String -> m a。也就是说,对于实现了MonadFail接口的任何类型以及任何类型的afail都可以采用字符串并产生由a参数化的该类型的实例。 / p>

对于Maybe afail s = Nothing

对于[a]fail s = []

对于IO afail引发包含字符串的异常。

许多人为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>