为什么没有关于Haskell(与Scala或C#相对)的协变和反变化的讨论?
我知道什么types的协变和逆变。 我的问题是为什么我在研究Haskell(而不是Scala)时还没有遇到这些概念的讨论?
Haskell的视图types与Scala或C#相比有一个根本的区别,我想说明一下这个区别是什么。
或者,也许我错了,我只是没有足够的Haskell学习:-)
主要有两个原因:
- Haskell缺乏子types的固有概念,所以一般而言,方差不太重要。
- 反variables主要出现在涉及可变性的地方,所以Haskell中的大多数数据types都是协变的,而且明确地区分这些数据types的价值不大。
然而,这些概念确实适用 – 例如,由fmap为Functor实例执行的提升操作实际上是协变的; 在类别理论中使用术语“共同/反对”来讨论函子。  contravariant包为contravariant函子定义了一个types类,如果你看一下实例列表,你会明白为什么我说它不太常见。 
 这个想法也隐含地出现在人工转换如何工作的地方 – 各种数字types类定义了从Integer和Rational等基本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中相当于叫做Maybe的Option有这样的定义: 
 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又使用这个术语),但这些术语意味着完全不同的东西。 术语不变式可以在很多地方使用。