haskell - Haskell:为什么“id”使这个函数不再是单子的?
问题描述
我试图理解为什么id
在下面序列的最后一行添加会删除单子方面:
Prelude> :t id
id :: a -> a
Prelude> :t Control.Monad.liftM2
Control.Monad.liftM2
:: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool
Prelude> :t Control.Monad.liftM2 (==)
Control.Monad.liftM2 (==)
:: (Monad m, Eq a) => m a -> m a -> m Bool
Prelude> :t Control.Monad.liftM2 (==) id
Control.Monad.liftM2 (==) id :: Eq a => (a -> a) -> a -> Bool
Prelude>
添加如何id :: a -> a
以最后一行的方式更改签名?
解决方案
您将类型固定到特定Monad
实例,即“函数阅读器”monad ( instance Monad ((->) a)
)。
id :: a -> a
并且您正在尝试将其用作 type 参数的参数m a
,因此:
m a ~ a -> a
m a ~ (->) a a
m a ~ ((->) a) a
m ~ (->) a
a ~ a
签名的其余部分是:
m a -> m Bool
由于m ~ (->) a
,结果类型为:
(->) a a -> (->) a Bool
(a -> a) -> (a -> Bool)
(a -> a) -> a -> Bool
(加上Eq a
使用的约束==
。)
这在无点代码中很有用,尤其是在使用Applicative
实例时,因为您可以隐式地将函数的参数“传播”到子计算:
nextThree = (,,) <$> (+ 1) <*> (+ 2) <*> (+ 3)
-- or
nextThree = liftA3 (,,) (+ 1) (+ 2) (+ 3)
nextThree 5 == (6, 7, 8)
uncurry' f = f <$> fst <*> snd
-- or
uncurry' f = liftA2 f fst snd
uncurry' (+) (1, 2) == 3