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