Applicative函子。 <*> 和<$>的类型签名详解

3
我们有签名:
(<$>) :: 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

Question:

((/) <$> Just 5) <*> Just 2
^^^^^^^^^^^^^^^^     @@@@@@

(<$>) :: Functor f     =>   (a -> b) -> f a -> f b
                                               ^^^
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
                          ^^^^^^^^^^    @@@

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

我在这里漏掉了什么?谢谢。


提示:首先写出(/)的类型,然后确定ab是什么。记住函数是柯里化的。 - Robin Zigmond
1个回答

6

虽然它是匹配的,但是(<$>)(<*>)函数中的fab是变量,并且每次使用该函数时这些变量都是不同的。

因此,更有意义的做法是在这里将这些函数定义为:

(<$>) :: 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 :: 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 :: Fractional m => Maybe (m -> m)Fractional m意味着Num m)。
正如我们已经发现的那样,b ~ (c -> d),因此m ~ c ~ d,因此表达式的类型为:((/) <$> Just 5) <*> Just 2 :: Fractional m => Maybe m

感谢您。似乎需要在以下位置进行一些更正:...因此我们知道 (/) <$> Just 5 其类型为 (/) <$> Just 5 :: (Num m, Fractional m) => Maybe (m -> m) - Max
你能给我更多关于Applicative的提示吗?我看到通常的多参数函数应用f x y z和applicative f <$> x <*> y <*> z之间的相似之处,但是我无法想象在通常的函数应用程序世界中有任何直接的<*>和<$>的类比。此外,我感觉部分应用在这里某种程度上也涉及到了? - Max
(/) <$> Just 5 的结果是 Just ((/) 5),所以你说的部分应用是正确的。Just ((/) 5) <*> Just 2 的结果是 Just ((/) 5 2),因此得到了 Just 2.5 - Willem Van Onsem
然而,以某种方式计算 f x y z,我们没有定义任何新函数(就像我们使用 <*> 和 <$> 一样...我仍然觉得这里缺少一些元素...)。 - Max
1
“我们不定义任何新函数”是什么意思? - Willem Van Onsem
让我们在聊天中继续这个讨论 - Max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接