4

我遇到的问题是这样的:

以与 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

但它不编译。

谁能指出我正确的方向?

4

6 回答 6

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-sugar 写成:

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

一般来说,我会坚持使用(>=>),它有很好的理论存在理由,因为它提供了最简洁的方式来陈述单子定律。

于 2010-01-14T19:51:03.970 回答
6

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

所以你需要做的是:定义一个以 aMaybe b作为参数的函数。如果那个参数是Nothing,它应该返回Nothing。如果参数是Just b,它应该返回g bcomposeMaybe应该返回函数与 f 的组合。

于 2010-01-14T14:30:53.403 回答
5

这是一个关于 Haskell monad 的优秀教程(尤其是第一个示例中使用的Maybe monad)。

于 2010-01-14T14:34:53.763 回答
4
composeMaybe :: (a -> Maybe b)
             -> (b -> Maybe c)
             -> (a -> Maybe c)
composeMaybe f g = \x ->

由于g接受 type 的参数b,但f产生 type 的值,如果要将结果传递给,则必须Maybe b对结果进行模式匹配。f xg

                         case f x of
                              Nothing -> ...
                              Just y  -> ...
于 2010-01-14T14:36:51.483 回答
3

一个非常相似的函数已经存在——一元绑定运算符,>>=. 它的类型(对于 Maybe monad)是Maybe a -> (a -> Maybe b) -> Maybe b,它是这样使用的:

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

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

于 2010-01-14T19:40:32.273 回答
0

composeMaybe请注意's 参数的类型与单子绑定运算符对其后一个参数所需的类型有多接近:

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
于 2010-01-19T20:46:26.407 回答