了解< $>的签名

时间:2015-01-09 21:53:55

标签: haskell ghci applicative

我的应用<$>运算符或多或少已经弄明白了,但我无法理解我通过以下示例获得的签名:

ghci>  let f x y z = x + y + z  -- f::Num a => a -> a -> a -> a
ghci> f <$> Just 2 <*> Just 3 <*> Just 4 
Just 9

我理解这个结果,但在检查以下类型时:

ghci> :t (<$> f)
(<$> f) :: Num a => ((a -> a -> a) -> b) -> a -> b  --This makes no sense to me

我理解的那个签名是:一个函数,它将(a -> a- > a) -> b函数和a作为参数并返回b。根据这个推理,我应该这样称呼:

 (<$>f) f 4

会产生Integer。  显然这不是真的,所以请你帮我理解如何阅读(<$> f)的类型?

2 个答案:

答案 0 :(得分:3)

  

(a -> a- > a) -> b函数和a作为参数并返回b的函数。

这是正确的。

  

根据这个推理,我应该这样称呼:

(<$>f) f 4
     

会产生Integer

不,因为f没有(a -> a -> a) -> b类型或与之兼容的类型。相反,它的类型为Num a => a -> a -> a -> a。也就是说,f取三个数字并产生一个数字,而我们正在寻找一个函数(函数类型为a -> a -> a)作为其第一个参数。

答案 1 :(得分:1)

<$>g b类型作为第二个参数,其中g是任何应用函子。

您正在传递f :: Num a => a -> a -> a -> a作为第二个参数。让我们忽略Num a上下文以保持简单。

因此,我们会g,b寻找g b = a -> a -> a -> a

让我们以前缀形式写出f的类型:

f :: (->) a ((->) a ((->) a a)) = g b

因此,g = (->) ab = ((->) a ((->) a a))。后者以中缀形式b = a -> a -> a

恰好(->) a是一个应用函子,所以<$> f类型检查。但请注意,<$>用于与您在示例中使用的Maybe完全不同的仿函数。因此混乱。

TL; DR:重载的标识符可以变换为适应其上下文的许多事物,可能以某种意想不到的方式。