繁体   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