在应用程序的上下文中理解Haskell类型系统

时间:2014-12-02 11:08:39

标签: haskell type-systems applicative

我正在玩Control.Applicative,我意识到我不了解Haskell类型系统的所有内容。

这是我在Ghci的实验:

λ :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

λ :t (<*>) (pure 2)
(<*>) (pure 2) :: (Num (a -> b), Applicative f) => f a -> f b

<*>的第一个参数的类型是f (a -> b)

  • 为什么这个表达式正确?
  • 如何与(pure 2)统一,因为常量2不属于a -> b类型?
  • Num (a -> b)是什么意思?具有a -> b类型的函数如何成为Num的实例?

1 个答案:

答案 0 :(得分:7)

<*>的第一个参数应该是f (a -> b)。所以给定(<*>) (pure x),只要x是某种功能,这就是很好的类型。

2的类型为Num a => a。换句话说,2可以是任何可能的类型,只要它是Num的实例。

因此,在表达式(<*>) (pure 2)中,如果2的类型是函数类型,并且该函数类型具有Num实例,则这是良好类型的。

当然,几乎没有理由要求函数拥有Num实例。但是编译器不知道这一点。所有它说的是如果有这样的实例,那么表达式就会变得很好。

(这类似于您有时会看到编译器希望某个类型同时成为IntegralFractional的实例的错误。对于人类来说,这是一个无意义的组​​合。对于一台机器,他们只是两个普通的班级......)