什么是 Maybe 类型,它是如何工作的?

What is the Maybe type and how does it work?

我刚开始在 Haskell 中编程,我遇到了以下定义:

calculate :: Float -> Float -> Maybe Float

Maybe a是普通数据类型,定义为:

data Maybe a = Just a | Nothing

因此有两种可能性:或者您将类型 a 的值定义为 Just a(如 Just 3),或者 Nothing 以防查询没有回答。

它旨在定义为一种定义非总函数输出的方法。

例如:假设您要定义sqrt。平方根仅针对正整数定义,因此您可以将 sqrt 定义为:

sqrt x | x >= 0 = Just $ ...
       | otherwise = Nothing

...计算x的平方根的方法。

有些人将 Nothing 与大多数编程语言中的 "null pointer" 进行比较。默认情况下,你不会为你定义的数据类型实现空指针(如果你这样做,所有这些 "nulls" 看起来都不一样),通过添加 Nothing 你有一个通用的空指针。

因此,使用 Maybe 表示可能无法计算输出是很有用的。您当然也可以在小于 0:

的值上出错
sqrt x | x >= 0 = Just $ ...
       | otherwise = error "The value must be larger or equal to 0"

但是错误通常不会在类型签名中提及,如果您不考虑它们,编译器也没有任何问题。 Haskell 也转向 total 函数:最好总是尝试至少 return 一个值(例如 Nothing)所有可能的输入。

如果你以后想使用Maybe a的结果,你需要写:

succMaybe :: Maybe Int -> Maybe Int
succMaybe (Just x) = Just (x+1)
succMaybe _ = Nothing

但是通过为第一种情况编写 Just,您以某种方式警告自己可能会发生 Nothing。您还可以通过引入 "default" 值来摆脱 Maybe

justOrDefault :: a -> Maybe a -> a
justOrDefault _ (Just x) = x
justOrDefault d _ = d

内置的maybe函数(注意小写),结合了前面两个函数:

maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing  = z

所以你指定了一个b(默认值)和一个函数(a -> b)。如果 Maybe aJust x,函数将应用于它并 returned,如果输入值是 Nothing,将使用默认值。

使用 Maybe a 可能会很困难,因为您总是需要考虑 Nothing 的情况,要简化这一点,您可以使用 Maybe monad.


Tom Schrijvers 还表明 Maybe 是类型代数中的后继函数:你向你的类型添加一个额外的值(Either 是一个加法(,) 是乘法的类型代数等价物)。