我们有签名:
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
让我们玩一下:
(/) <$> Just 5 <*> Just 2
=> Just 2.5
((/) <$> Just 5 ) <*> Just 2
=> Just 2.5
( Just (\x -> 5/x ) ) <*> Just 2
=> Just 2.5
问题:
((/) <$> Just 5) <*> Just 2
^^^^^^^^^^^^^^^^ @@@@@@
(<$>) :: Functor f => (a -> b) -> f a -> f b
^^^
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
^^^^^^^^^^ @@@
我认为^^^部分应按其类型匹配。 <$>
的返回类型为什么在签名中在视觉上与<*>
的输入类型不匹配?
我在这里想念什么?谢谢。
答案 0 :(得分:6)
它确实匹配,但是f
和a
函数的b
,(<$>)
和(<*>)
是变量,并且每个变量都是不同的变量使用该功能的时间。
因此在这里将函数定义为:
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative g => g (c -> d) -> g c -> g d
因此,这意味着^
和@
确实匹配:
((/) <$> Just 5) <*> Just 2
^^^^^^^^^^^^^^^^ @@@@@@
(<$>) :: Functor f => (a -> b) -> f a -> f b
^^^
(<*>) :: Applicative g => g (c -> d) -> g c -> g d
^^^^^^^^^^ @@@
因此我们知道(/) <$> Just 5
的类型为f b
和g (c -> d)
,而Just 2
的类型为g c
。由于Just 2
的类型为Just 2 :: Num n => Maybe n
,因此这意味着g ~ Maybe
和c ~ n
(此处x ~ y
的意思是x
和y
是相同的类型)。此外,我们可以推导f b ~ g (c -> d)
,f ~ Maybe
和b ~ (c -> d)
。
我们可以进一步分析(/) <$> Just 5
表达式。我们知道Just 5
的类型为Num m => Maybe m
,因此意味着a ~ m
。函数(/)
的类型为(/) :: Fractional k => k -> k -> k
,因此意味着a ~ b ~ k ~ m
,因此我们知道(/) <$> Just 5
的类型为(/) <$> Just 5 :: (Num m, Fractional m) => Maybe (m -> m)
,或更不冗长的{{1} }((/) <$> Just 5 :: Fractional m => Maybe (m -> m)
表示Fractional m
)。
我们已经发现Num m
,所以这意味着b ~ (c -> d)
,因此表达式的类型是:m ~ c ~ d
。