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