适用函子。 <*>和<$>的类型签名详细

时间:2019-09-07 18:54:10

标签: haskell applicative

我们有签名:

(<$>) :: 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
                          ^^^^^^^^^^    @@@

我认为^^^部分应按其类型匹配。 <$>的返回类型为什么在签名中在视觉上与<*>的输入类型不匹配?

我在这里想念什么?谢谢。

1 个答案:

答案 0 :(得分:6)

它确实匹配,但是fa函数的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 bg (c -> d),而Just 2的类型为g c。由于Just 2的类型为Just 2 :: Num n => Maybe n,因此这意味着g ~ Maybec ~ n(此处x ~ y的意思是xy是相同的类型)。此外,我们可以推导f b ~ g (c -> d)f ~ Maybeb ~ (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