为什么安全的部分函数使用 Maybe 而不是泛化到任何 Monad

Why do safe partial functions use Maybe instead of generalizing to any Monad

我知道有些人认为 fail 是个错误,我明白为什么。 (似乎 MonadPlus 是用来取代它的)。但只要它存在,部分函数使用 failpure 而不是 JustNothing 似乎是有意义的。因为这会让你做你目前能做的一切,甚至更多,所以像 safeHead 这样的东西可以给你传统的 Just/Nothing 或者你可以 return [x]/[].

从我读到的关于 MonadPlus 的内容来看,它似乎比使用 fail 更好。但我对它的了解还不够肯定,而且它也可能涉及进入 Prelude,这可能是个好主意,但比仅使用 fail.[=25= 会有更大的变化。 ]

所以我想我的问题是为什么部分函数不使用 failMonadPlus,两者似乎都比使用具体类型更好。

So I guess my question is why partial functions don't use fail OR MonadPlus, both seem better than using a concrete type.

好吧,我不能说写它们的人的动机,但我当然同意他们的偏好。我在这里要说的是,我们中的许多人都遵循一种思想流派,即像 Maybe 这样的具体类型将是我们的默认选择,因为:

  1. 简单具体;
  2. 它完美地模拟了域;
  3. 它可以通用地映射到您能想到的任何更抽象的解决方案。

a -> Maybe b 这样的类型完美地模拟了偏函数的概念,因为偏函数要么 returns 结果 (Just b) 要么不结果 (Nothing),并且没有更细微的区别(例如,没有不同种类的 "nothingness")。

第 3 点可以用这个函数来说明,它通常将 Maybe a 转换为 Alternative 的任何实例(它是 MonadPlus 的超类):

import Control.Applicative

fromMaybe :: Alternative f => Maybe a -> f a
fromMaybe Nothing = empty
fromMaybe (Just a) = pure a

因此,按照这种理念,您可以根据 Maybe 编写偏函数,如果您需要将结果放在其他 Alternative 实例中,那么您可以使用 fromMaybe 充当适配器。

然而,这可以反过来争论,你会得到这个:

safeHead :: Alternative f => [a] -> f a
safeHead [] = empty
safeHead (a:_) = pure a

...因为仅输入 safeHead xsfromMaybe (safeHead xs) 短。各有各的。