[英]What are the key differences between Java 8's Optional, Scala's Option and Haskell's Maybe?
[英]Plan B, or what's the opposite of Maybe's >>=?
我們來看兩個功能:
f :: a -> Maybe b
g :: b -> Maybe c
函數>>=
將以這樣的方式工作: f >>= g
只有當它不是Nothing
時才用f
的結果執行g
。 換句話說,它需要f
和g
都能成功產生任何結果。
我正在實現一個解析器,並意識到我的詞法分析器會從中獲益。 那是:
f :: a -> Maybe b
g :: a -> Maybe b
planb :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b)
planb f g = \x -> case f x of
Nothing -> g x
res -> res
這意味着嘗試f
,如果失敗,請嘗試g
作為備份計划。 使用詞法分析器意味着嘗試將令牌類型與當前輸入匹配,如果失敗,請嘗試匹配另一個令牌類型(最終將為所有令牌類型鏈接)。
搜索Hoogle沒有導致任何這樣的功能,但對我來說這樣的功能似乎在很多地方都很有用!
我的問題是,我是否應該使用planb
的變體? 如果沒有,我是否做了非凡的事情,有更好的方法來達到我想要的目標?
PS我想到這樣的功能對於Monad
來說是否有意義,但是對於我在Maybe
之外並沒有那么多意義, Maybe
還有其他一些。
Alternative
類型正是這樣做的,它與MonadPlus
非常相似,但可能更為通用。
import Control.Applicative
-- most general form
planb :: (Applicative g, Alternative f) => g (f a) -> g (f a) -> g (f a)
planb = liftA2 (<|>)
-- specialized to (->) and Maybe
planb' :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b)
planb' = planb
-- equivalent to planb' (and planb) but without the fancy combinators
planb'' :: (a -> Maybe b) -> (a -> Maybe b) -> a -> Maybe b
planb'' f g x = f x <|> g x
將其插入一個簡單的測試用例:
test :: Maybe Int
test = do
a <- planb' (const Nothing) id (Just 1)
b <- planb' id id (Just 1)
c <- planb' id (const Nothing) (Just 1)
return $ a + b + c
生成預期結果:
*Main> test
Just 3
請注意,您的planb
函數實際上只需要對Maybe
值進行操作; 調用函數來生成它們可以被考慮在內。
planb :: Maybe a -> Maybe a -> Maybe a
planb Nothing b = b
planb a _ = a
你會把它planb (fx) (gx)
來得到一個Maybe
結果。
考慮到這一點,請查看MonadPlus
類 (正如Franky在評論中所建議的那樣):
planb = mplus
您可能還對msum
感興趣, msum
會獲取Maybe
值列表並返回第一個(如果有)不是Nothing
。 這是一個方便的功能:
matchSomehow :: [a -> Maybe b] -> a -> Maybe b
matchSomehow fs a = msum $ map ($a) fs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.