在Haskell中编写两个错误提升函数

时间:2010-01-14 14:18:17

标签: function haskell error-handling composition

我遇到的问题是:

  

以类似于mapMaybe的方式,定义   功能:        composeMaybe ::(a-> Maybe b) - > (b - >也许c) - > (a->也许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

但它没有编译。

有人能指出我正确的方向吗?

6 个答案:

答案 0 :(得分:7)

您正在寻找的工具已经存在。 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 - 糖为:

composeMaybe f g x = do 
    y <- f x
    g y

一般来说,我只是坚持使用(>=>),这有很好的理论原因,因为它提供了最简洁的方式来陈述monad定律。

答案 1 :(得分:6)

首先:如果它应该是g.f,而不是f.g,因为你想要一个与f相同的参数的函数,并给出与g相同的返回值。但是这不起作用,因为f的返回类型不等于g的参数类型(f的返回类型在其中有一个Maybe而g的参数类型没有)。

所以你需要做的是:定义一个以Maybe b为参数的函数。如果该参数为Nothing,则应返回Nothing。如果参数为Just b,则应返回g bcomposeMaybe应该使用f。

返回函数的组成

答案 2 :(得分:5)

这是一个关于Haskell monad的优秀tutorial(特别是 Maybe monad ,在第一个例子中使用)。

答案 3 :(得分:4)

composeMaybe :: (a -> Maybe b)
             -> (b -> Maybe c)
             -> (a -> Maybe c)
composeMaybe f g = \x ->

由于g采用b类型的参数,但f生成类型为Maybe b的值,因此您必须对{{1}的结果进行模式匹配如果要将结果传递给f x

g

答案 4 :(得分:3)

一个非常相似的函数已经存在 - monadic绑定运算符>>=。它的类型(对于Maybe monad)是Maybe a -> (a -> Maybe b) -> Maybe b,它的用法如下:

Just 100 >>= \n -> Just (show n) -- gives Just "100"

它与你的composeMaybe函数不完全相同,它使一个函数返回Maybe而不是第一个参数的直接Maybe值。但是您可以使用此运算符非常简单地编写composeMaybe函数 - 它几乎与普通复合函数(.) f g x = f (g x)的定义一样简单。

答案 5 :(得分:0)

请注意composeMaybe的参数类型与monadic绑定运算符对其后一个参数的需求有多接近:

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