簡體   English   中英

在Haskell中編寫兩個錯誤提升函數

[英]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

fg的順序對於構圖是向后的,那么更好的名字怎么樣?

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM