函数应用程序作为标识Monad:它是如何成为Monad类型类的实例?

时间:2014-04-08 10:17:17

标签: haskell monads

我正在阅读“功能编程工艺”(第2版),其中第404页简要提到功能应用程序也是Monad,作者称之为Monad身份。

然而,我很难想象如何将函数应用程序作为Haskell中类型类Monad的实例,与Maybe数据结构成为Monad类型类的实例一样。

这也引出了另一个问题:函数应用程序如何成为类型构造函数(与Maybe相同)?

有人可以对这个谜团有所了解吗?

2 个答案:

答案 0 :(得分:8)

函数应用程序本身不是monad,它是Identity monad中的绑定。

newtype Identity a = Identity { runIdentity :: a }
instance Monad Identity where
    return = Identity
    (Identity a) >>= f = f a -- :: Identity a -> (a -> Identity b) -> Identity b
    join (Identity (Identity a)) = Identity a
    fmap f (Identity a) = Identity $ f a

因此,如果您将所有函数和值提升到标识monad中,则可以使用do-notation,它只是在普通函数应用程序中进行大量记录。

您不应该将此与类型为(->) a的Monad实例混淆,后者与读者Monad:newtype Reader a b = Reader { runReader :: a -> b }同构。

答案 1 :(得分:1)

[编辑:我还没看过这本书,似乎nimish's answer似乎我误解了你的问题]

r -> a也可以写成(->) r a,它是(->) r类型构造函数(可以读作“来自r的函数”),可以给出monad实例。要定义我们需要提供的实例

return :: a -> (r -> a)
(>>=)  :: (r -> a) -> (a -> (r -> b)) -> r -> b

前者很容易。对于后者,这是一个暗示。完全应用后,(>>=)会使用三个参数,类型为r -> aa -> r -> br。现在应该清楚如何将这些组合起来以获得b

您的知识也将从实施中受益

join :: (r -> (r -> a)) -> (r -> a)

注意:我不明白为什么有人会称之为“身份monad”。身份monad通常是newtype Identity a = Identity a。来自r的“函数”的monad是(同构的)Reader monad。