Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't there many discussions about co- and contra-variance in Haskell (as opposed to Scala or C#)?

I know what covariance and contravariance of types are. My question is why haven't I encountered discussion of these concepts yet in my study of Haskell (as opposed to, say, Scala)?

It seems there is a fundamental difference in the way Haskell views types as opposed to Scala or C#, and I'd like to articulate what that difference is.

Or maybe I'm wrong and I just haven't learned enough Haskell yet :-)

like image 586
ErikR Avatar asked Feb 15 '12 22:02

ErikR


2 Answers

There are two main reasons:

  • Haskell lacks an inherent notion of subtyping, so in general variance is less relevant.
  • Contravariance mostly appears where mutability is involved, so most data types in Haskell would simply be covariant and there'd be little value to distinguishing that explicitly.

However, the concepts do apply--for instance, the lifting operation performed by fmap for Functor instances is actually covariant; the terms co-/contravariance are used in Category Theory to talk about functors. The contravariant package defines a type class for contravariant functors, and if you look at the instance list you'll see why I said it's much less common.

There are also places where the idea shows up implicitly, in how manual conversions work--the various numeric type classes define conversions to and from basic types like Integer and Rational, and the module Data.List contains generic versions of some standard functions. If you look at the types of these generic versions you'll see that Integral constraints (giving toInteger) are used on types in contravariant position, while Num constraints (giving fromInteger) are used for covariant position.

like image 88
C. A. McCann Avatar answered Nov 06 '22 13:11

C. A. McCann


There are no "sub-types" in Haskell, so covariance and contravariance don't make any sense.

In Scala, you have e.g. Option[+A] with the subclasses Some[+A] and None. You have to provide the covariance annotations + to say that an Option[Foo] is an Option[Bar] if Foo extends Bar. Because of the presence of sub-types, this is necessary.

In Haskell, there are no sub-types. The equivalent of Option in Haskell, called Maybe, has this definition:

data Maybe a = Nothing | Just a

The type variable a can only ever be one type, so no further information about it is necessary.

like image 22
dflemstr Avatar answered Nov 06 '22 13:11

dflemstr