[英]Composing two error-raising functions in Haskell
我得到的問題說:
以類似於mapMaybe的方式,定義函數:composeMaybe ::(a-> Maybe b) - >(b - > Maybe c) - >(a-> Maybe c),它組成兩個錯誤提升函數。
類型Maybe a和函數mapMaybe的編碼如下:
data Maybe a = Nothing | Just a
mapMaybe g Nothing = Nothing
mapMaybe g (Just x) = Just (g x)
我嘗試使用這樣的組合:
composeMaybe f g = f.g
但它沒有編譯。
有人能指出我正確的方向嗎?
您正在尋找的工具已經存在。 Control.Monad中有兩個Kleisli組合運算符。
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
當m = Maybe時,composeMaybe的實現變得明顯:
composeMaybe = (>=>)
看(>=>)
的定義,
f >=> g = \x -> f x >>= g
如果您想以自己的方式考慮它,可以內聯
composeMaybe f g x = f x >>= g
或者可以用do
-sugar寫成:
composeMaybe f g x = do
y <- f x
g y
一般來說,我只是堅持使用(>=>)
,這有很好的理論原因,因為它提供了最簡潔的方式來陳述monad定律。
首先:如果它應該是gf
,而不是fg
因為你想要一個與f相同的參數的函數,並給出與g相同的返回值。 但是這不起作用,因為f的返回類型不等於g的參數類型(f的返回類型中有一個Maybe而g的參數類型沒有)。
所以你需要做的是:定義一個以Maybe b
為參數的函數。 如果該參數為Nothing
,則應該返回Nothing
。 如果參數是Just b
,它應該返回gb
。 composeMaybe
應該用f返回函數的組成。
這是一個關於Haskell monad的優秀教程 (特別是在第一個例子中使用的Maybe monad )。
composeMaybe :: (a -> Maybe b)
-> (b -> Maybe c)
-> (a -> Maybe c)
composeMaybe f g = \x ->
由於g
采用類型b
的參數,但f
生成類型為Maybe b
的值,因此如果要將結果傳遞給g
,則必須對fx
的結果進行模式匹配。
case f x of
Nothing -> ...
Just y -> ...
一個非常相似的函數已經存在 - monadic綁定運算符, >>=
。 它的類型(對於Maybe monad)是Maybe a -> (a -> Maybe b) -> Maybe b
,它的用法如下:
Just 100 >>= \n -> Just (show n) -- gives Just "100"
它與你的composeMaybe
函數不完全相同,它接受一個函數返回Maybe而不是第一個參數的直接Maybe值。 但是你可以用這個操作符非常簡單地編寫你的composeMaybe
函數 - 它幾乎和普通composeMaybe
函數的定義一樣簡單, (.) fgx = f (gx)
。
請注意composeMaybe
的參數類型與composeMaybe
綁定運算符對其后一個參數的需求有多接近:
ghci> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
f
和g
的順序對於構圖是向后的,那么更好的名字怎么樣?
thenMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
thenMaybe f g = (>>= g) . (>>= f) . return
鑒於以下定義
times3 x = Just $ x * 3
saferecip x
| x == 0 = Nothing
| otherwise = Just $ 1 / x
例如,一個人可以
ghci> saferecip `thenMaybe` times3 $ 4
Just 0.75
ghci> saferecip `thenMaybe` times3 $ 8
Just 0.375
ghci> saferecip `thenMaybe` times3 $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 0
Nothing
ghci> times3 `thenMaybe` saferecip $ 1
Just 0.3333333333333333
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.