我正在阅读“功能编程工艺”(第2版),其中第404页简要提到功能应用程序也是Monad,作者称之为Monad身份。
然而,我很难想象如何将函数应用程序作为Haskell中类型类Monad的实例,与Maybe数据结构成为Monad类型类的实例一样。
这也引出了另一个问题:函数应用程序如何成为类型构造函数(与Maybe相同)?
有人可以对这个谜团有所了解吗?
答案 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 -> a
,a -> r -> b
和r
。现在应该清楚如何将这些组合起来以获得b
。
您的知识也将从实施中受益
join :: (r -> (r -> a)) -> (r -> a)
注意:我不明白为什么有人会称之为“身份monad”。身份monad通常是newtype Identity a = Identity a
。来自r
的“函数”的monad是(同构的)Reader monad。