为什么我要使用Maybe而不是List?

时间:2016-04-20 22:44:44

标签: list haskell types maybe

看到Maybe类型与null和singleton列表的集合是同构的,为什么当我只能使用列表来容纳缺席时,是否有人想要使用Maybe类型?

7 个答案:

答案 0 :(得分:14)

因为如果您将列表与模式[][x]匹配,这不是一个详尽的匹配,并且您会收到相关警告,强制您添加另一个永远不会获得的案例打电话或忽略警告。

MaybeNothingJust x相匹配但是详尽无遗。因此,如果您未能匹配其中一个案例,您将只会收到警告。

如果您选择的类型使得它们只能表示您实际可能产生的值,则可以依靠非详尽性警告来告诉您代码中您忘记检查给定案例的错误。如果您选择更多“许可”类型,您将始终考虑警告是代表实际错误还是仅仅是不可能的情况。

答案 1 :(得分:11)

您应该努力获得准确的类型。 也许表示只有一个值或没有值。许多命令式语言通过值 null 来表示“无”情况。

如果您选择了一个列表而不是 Maybe ,那么您的所有功能都将面临他们获得包含多个成员的列表的可能性。可能其中许多只会被定义为一个值,并且必须在模式匹配时失败。通过使用 Maybe ,您可以完全避免一类运行时错误。

答案 2 :(得分:8)

在现有(和正确)答案的基础上,我会提到基于类型类的答案。

不同的类型传达不同的意图 - 返回Maybe a表示可能失败的计算,而[a]可能表示非确定性(或者,简单来说,多个可能的返回值)。

这使得不同类型具有不同的类型类实例 - 这些实例迎合了类型传达的基本本质。取Alternative及其运算符(<|>),表示在给定的参数之间组合(或选择)的含义。

  • Maybe a 合并可能失败的计算只意味着取得第一个不是Nothing
  • 的计算
  • [a] 组合两个计算,每个计算都有多个返回值,这意味着将所有可能的值连接在一起。

然后,根据您的函数使用的类型,(<|>)的行为会有所不同。当然,你可以说你不需要(<|>)或类似的东西,但是你错过了Haskell的一个主要优势:它有很多高级别的组合库。

作为一般规则,我们希望我们的类型尽可能贴合和直观。这样,我们就不会与标准库作斗争,而且我们的代码更具可读性。

答案 3 :(得分:4)

Lisp,Scheme,Python,Ruby,JavaScript等,每个只需要一种类型,你可以在Haskell中用一个大的类型代表它。处理JavaScript(或其他)值的每个函数都必须准备好接收数字,字符串,函数,文档对象模型的一部分等,如果出现意外情况则抛出异常。使用Haskell等类型语言编程的人更喜欢限制可能发生的意外事件的数量。他们还喜欢使用类型表达 ideas ,使类型有用(和机器检查)文档。类型越接近表示预期意义,它们就越有用。

答案 4 :(得分:3)

因为可能的列表数量无穷大,而且Maybe类型的可能值有限。它完美地代表了一件事或没有任何其他可能性的东西。

答案 5 :(得分:2)

有几个答案在这里提到了详尽无遗的因素。我认为这是一个因素,但不是最大的一个因素,因为有一种方法可以将列表视为Maybe s,listToMaybe函数说明了这一点:

listToMaybe :: [a] -> Maybe a
listToMaybe [] = Nothing
listToMaybe (a:_) = Just a

这是一个详尽的模式匹配,它排除了任何直接的错误。

我强调的因素是,通过使用更精确地模拟代码行为的类型,可以消除在使用更通用的替代方案时可能出现的潜在行为。比如说您在代码中有一些上下文,其中使用了a -> [b]形式的类型,尽管唯一正确的替代方法(根据程序的规范)是空的或单例列表。尽可能努力地强制执行这个上下文应该遵守该规则的约定,你仍然可能会陷入困境并且:

  1. 不知何故,该上下文中使用的函数将生成两个或更多项的列表;
  2. 不知何故,使用在该上下文中生成的结果的函数将观察列表是否包含两个或更多项,并且在这种情况下行为不正确。
    • 示例:某些代码期望不超过一个值将盲目地打印列表的内容,从而在只有一个项目时打印多个项目。
  3. 但是如果你使用Maybe,那么确实必须有一个值或者没有,并且编译器强制执行此操作。

答案 6 :(得分:0)

即使是同构的,例如由于搜索空间的增加,QuickCheck将运行得更慢。