我在查看自由单子时遇到了这个问题,但已将其归结为一个更小的例子。
在 Haskell 中,我们有以下类型:
fmap :: Functor f => (a -> b) -> f a -> f b
假设我们还有以下函数:
foo :: Num a => p -> a
foo = \_ -> 1
然后
fmap foo :: (Functor f, Num b) => f a -> f b
-- and
fmap (fmap foo)
:: (Functor f1, Functor f2, Num b) => f1 (f2 a) -> f1 (f2 b)
那么人们可能会认为我们只能应用于fmap (fmap foo)
某种类型(Functor f1, Functor f2) => f1 (f2 a)
,但是
fmap (fmap foo) foo :: (Functor f, Num b, Num (f a)) => p -> f b
什么?为什么要检查此类型,以及为什么它具有给定的类型?
如果有人能解释一下这里发生了什么,我将不胜感激。很抱歉标题含糊不清,但我对这里发生的事情了解不够多,无法更具体。我很乐意在回复澄清后将其更新为更易于搜索的内容。
foo
是一个函数,因此使用fmap
它(作为第二个参数)选择函数的实例,Functor
其中fmap = (.)
。所以你问为什么fmap foo . foo
有给定的类型,这是一个简单的统一问题:因此我们有
x = f a
,并且结果类型签名是(Num (f a), Functor f, Num b) => p -> f b
。