为什么Haskell中没有很多关于共同和反差的讨论(与Scala或C#相反)?

时间:2012-02-15 22:51:34

标签: haskell covariance contravariance

我知道类型的协方差和逆变。我的问题是为什么我在Haskell的研究中没有遇到过对这些概念的讨论(而不是Scala)?

似乎Haskell查看类型与Scala或C#相反的方式存在根本区别,我想清楚地说明这种区别是什么。

或许我错了,我还没有学到足够的Haskell: - )

3 个答案:

答案 0 :(得分:59)

主要有两个原因:

  • Haskell缺乏一种固有的子类型概念,因此一般来说方差不太相关。
  • 逆变性主要出现在涉及可变性的地方,因此Haskell中的大多数数据类型只是协变的,并且明确区分它几乎没有价值。

然而,这些概念确实适用 - 例如,fmapFunctor个实例执行的提升操作实际上是协变的;术语共同/逆变在类别理论中用于谈论仿函数。 contravariant package为逆变函子定义了一个类型类,如果你查看实例列表,你就会明白为什么我说它不太常见。

还有一些地方隐含地显示了这个想法,手动转换的工作方式 - 各种数字类型类定义了与IntegerRational等基本类型之间的转换,以及模块{ {1}}包含某些标准函数的通用版本。如果您查看the types of these generic versions,您会看到Data.List约束(给出Integral)用于逆变位置的类型,而toInteger约束(给出Num )用于协变位置。

答案 1 :(得分:21)

Haskell中没有“子类型”,所以协方差和逆变没有任何意义。

在Scala中,你有例如Option[+A]子类Some[+A]None。您必须提供协方差注释+,以表明如果Option[Foo] Option[Bar]Foo extends Bar。由于存在子类型,这是必要的。

在Haskell中,没有子类型。 Haskell中的Option等价于Maybe,具有以下定义:

data Maybe a = Nothing | Just a

类型变量a只能是一种类型,所以不需要有关它的更多信息。

答案 2 :(得分:7)

如前所述,Haskell没有子类型。但是,如果您正在查看类型类,可能不清楚如何在没有子类型的情况下工作。

类型类指定类型的谓词,而不是类型本身。因此,当Typeclass有一个超类(例如Eq a => Ord a)时,这并不意味着实例是子类型,因为只有谓词是继承的,而不是类型本身。

此外,共同,反对和方差在不同的数学领域意味着不同的东西(见维基百科)。例如,covariant和contravariant这两个术语用于仿函数(后者又用于Haskell),但这些术语意味着完全不同的东西。术语不变量可以在很多地方使用。