实现`Monad(( - >)e)`

时间:2014-12-11 04:26:58

标签: haskell monads

Typeclassopedia介绍了这个练习:

  

为(( - >)e)实现Monad实例。

这是MyMonad类。

class (MyMonad m) where
    ret     :: a   -> m a
    flatMap :: m a -> (a -> m b) -> m b

然后,我开始尝试为((->) e)实现Monad实例。

instance (MyMonad (-> e)) where
    ret x       = ...
    flatMap m f = ...

但是,我对((->) e)的含义没有直觉。

请帮助我理解它,并给我一个解决ret的暗示。

2 个答案:

答案 0 :(得分:6)

这里有一些语法技巧。可能更容易将(->) e视为(e ->),或者更清楚地说,如果我们写

type Arr a b = a -> b

然后(->) eArr e大致相同。

那么ret的类型是什么?它最终成为

ret :: a -> (e -> a)

现在应该更容易解决。

答案 1 :(得分:5)

如果Haskell允许类型操作符,这将更容易理解 各部门,IMO。类型

a -> b

相当于

(->) a b

这意味着

(->) a

相同
(a ->)

它实质上是说它是参数化的函数类型 输出类型。所以这意味着我们应该

ret :: a -> (((->) r) a)

或等效

ret :: a -> ((r ->) a)      -- Note that this is invalid Haskell, it's using our magical TypeOperatorSections extension
ret :: a -> (r -> a)
ret :: a -> r -> a

警告:蠢货!

嗯,这种类型看起来非常简单和熟悉。如果我们在Hoogle上查找,那么 第一个结果是

const :: a -> b -> a

其余结果大约为seqpar,其他更高级 我们可以相当肯定的功能并不是我们正在寻找的东西。所以 const它是:

instance MyMonad ((->) r) where
    return = const

对于flatMap的实现,我们可以从注释我们的参数开始 与他们的类型:

flatMap (m :: r -> a) (f :: a -> (r -> b)) = _

所以我们有一个函数,当给定r时返回a,以及一个函数 给定ar返回b,我们想要flatMap m f :: r -> b。因为我们 没有r类型的参数,让我们介绍一个:

flatMap m f = \r -> _

如果您正在使用打字孔,GHC现在会告诉您需要一些东西 输入b。相关的绑定是

m :: r -> a
f :: a -> r -> b
r :: r

只有一种方法可以获得am来自flatMap m f = \r -> _ (m r) ,所以

a -> b

现在我们有GHC告诉我们,我们需要f :: a -> r -> b r :: r 类型的相关信息 绑定

flatMap m f = \r -> f (m r) r

这对我来说非常简单:

test :: Int -> Int
test =
    (*2) `flatMap` (\x1 ->
        (^3) `flatMap` (\x2 ->
            (7-) `flatMap` (\x3 ->
                return (x1 * x2 + x3)
            )
        )
    )

我们的代码类型检查!现在是时候测试一下了。期望的行为是 我们将相同的输入参数传递给do块中的几个函数(你 可以使用RebindableSyntax 如果你真的想用do notation),那就像

test' x = (2*x) * (x^3) + (7-x)

应与

相同
> test 5 == test' 5
True
> test 100 == test' 100
True

对于我们的实施,它确实有效:

{{1}}