如何以及为什么在Haskell中将ap定义为liftM2 id

luk*_*all 12 haskell applicative

在尝试更好地理解Applicative的同时,我查看了<*>的定义,该定义往往被定义为ap,后者又被定义为:

ap                :: (Monad m) => m (a -> b) -> m a -> m b
ap                =  liftM2 id
Run Code Online (Sandbox Code Playgroud)

查看liftM2和id的类型签名,即:

liftM2  :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
id                      :: a -> a
Run Code Online (Sandbox Code Playgroud)

我无法理解如何通过传递id,类型签名的相关部分似乎从转换(a1 -> a2 -> r) -> m a1m (a -> b).我在这里错过了什么?

Tom*_*ett 17

类型变量afrom id可以在任何类型实例化,在这种情况下,该类型是a -> b.

因此,我们实例化id(a -> b) -> (a -> b).现在,类型变量a1from liftM2正在实例化(a -> b),a2正在实例化a,并且r正在实例化b.

把它们放在一起,liftM2实例化((a -> b) -> (a -> b)) -> m (a -> b) -> m a -> m b,和liftM2 id :: m (a -> b) -> m a -> m b.