Haskell/库/Maybe
Maybe
数据类型用于可能不成功的函数。完整的描述在 Maybe 单子 章中。
标准 Prelude 定义 Maybe
类型如下
data Maybe a = Nothing | Just a
回想一下,类型 a 是多态的,可以包含复杂类型,甚至可以包含其他单子(如 IO () 类型)。
标准 分层库 中的 Data.Maybe
模块包含大量用于处理 Maybe 值的函数。
两个明显的函数提供关于 Maybe 值的信息
isJust
在给定 Just _
形式的参数时返回 True。
isJust :: Maybe a -> Bool
isJust (Just _) = True
isJust Nothing = False
isNothing
如果其参数为 Nothing
则返回 True。
isNothing :: Maybe a -> Bool
isNothing (Just _) = False
isNothing Nothing = True
有一些函数用于将 Maybe 值转换为非 Maybe 值。
maybe
将给定函数应用于 Just
传递的内部值,但在给定 Nothing
时返回默认值。
maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing = z
我们可能希望在不将任何函数应用于 Just
的情况下使用 maybe
。我们可以通过使用函数 id
调用 maybe
来做到这一点。Data.Maybe
已经有了这个,叫做 fromMaybe
fromMaybe :: a -> Maybe a -> a
fromMaybe z = maybe z id
注意使用无点风格。maybe z id
评估为一个函数,它可以接受 Maybe
值。
列表和 Maybe
之间的许多相似之处在 列表单子 章中讨论。鉴于这些联系,有一些函数可以在这两者之间转换
失败的计算返回列表的 []
和 Maybe 的 Nothing
。listToMaybe
从列表转换为 Maybe 单子。由于 Maybe
只能容纳一个值,listToMaybe
仅从列表中获取第一个解决方案。
listToMaybe :: [a] -> Maybe a
listToMaybe [] = Nothing
listToMaybe (x:_) = Just x
当然,listToMaybe
的反向是 maybeToList
maybeToList :: Maybe a -> [a]
maybeToList Nothing = []
maybeToList (Just x) = [x]
有一些函数类似于普通的 Prelude 列表操作函数,但专门针对 Maybe 值。
我们可能希望有一个 OR 函数,它不会因为一个部分失败而使整个计算失败。
给定一个 Maybe 值列表,catMaybes
提取所有 Just _
形式的值,并剥离 Just
构造函数。列表推导在这里完成了这项工作(正如我们在 模式匹配 章中所展示的那样)。
catMaybes :: [Maybe a] -> [a]
catMaybes ms = [ x | Just x <- ms ]
mapMaybe
将函数应用于列表并收集成功的结果。它可以理解为已知函数的组合
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe f xs = catMaybes (map f xs)
然而,Data.Maybe
中的实际定义遍历列表,效率可能更高
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe _ [] = []
mapMaybe f (x:xs) =
case f x of
Just y -> y : mapMaybe f xs
Nothing -> mapMaybe f xs
与其说是 OR,不如说是当且仅当所有都成功时才收集值。
sequence :: [Maybe a] -> Maybe [a]
sequence [] = Just []
sequence (Nothing:xs) = Nothing
sequence (Just x:xs) = case sequence xs of
Just xs' -> Just (x:xs')
_ -> Nothing