为什么没有关于Haskell(与Scala或C#相对)的协变和反变化的讨论?

我知道什么types的协变和逆变。 我的问题是为什么我在研究Haskell(而不是Scala)时还没有遇到这些概念的讨论?

Haskell的视图types与Scala或C#相比有一个根本的区别,我想说明一下这个区别是什么。

或者,也许我错了,我只是没有足够的Haskell学习:-)

主要有两个原因:

  • Haskell缺乏子types的固有概念,所以一般而言,方差不太重要。
  • 反variables主要出现在涉及可变性的地方,所以Haskell中的大多数数据types都是协变的,而且明确地区分这些数据types的价值不大。

然而,这些概念确实适用 – 例如,由fmapFunctor实例执行的提升操作实际上是协变的; 在类别理论中使用术语“共同/反对”来讨论函子。 contravariant包为contravariant函子定义了一个types类,如果你看一下实例列表,你会明白为什么我说它不太常见。

这个想法也隐含地出现在人工转换如何工作的地方 – 各种数字types类定义了从IntegerRational等基本types转换的模式,模块Data.List包含了一些标准函数的通用版本。 如果你看看这些generics版本的types,你会发现Integral约束(给予toInteger )用于逆变位置的types,而Num约束(来自fromInteger )用于协变位置。

Haskell中没有“子types”,所以协变性和逆变性没有任何意义。

在斯卡拉,你有例如Option[+A]的子类Some[+A]None 。 如果Foo extends Bar则必须提供协方差标注+来说明一个Option[Foo]是一个Option[Bar] 。 由于子types的存在,这是必要的。

在Haskell中,没有子types。 Haskell中相当于叫做MaybeOption有这样的定义:

 data Maybe a = Nothing | Just a 

typesvariablesa只能是一个types,所以不需要进一步的信息。

如上所述,Haskell没有子types。 但是,如果你正在研究types类,那么可能不清楚如何在没有子types的情况下工作。

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

而且,在不同的math领域中,co-,contra-和in-in意味着不同的事物(参见维基百科)。 例如covariant和contravariant这两个术语被用在functor中(而Haskell又使用这个术语),但这些术语意味着完全不同的东西。 术语不变式可以在很多地方使用。