Thursday, July 17, 2014

Scala covariant and invariant

http://abstractlayers.com/2014/03/06/covariance-and-contravariance-in-scala/

If you have 2 classes A,B such that A is subtype of B, and
if you have 2 parameterized types C[A],C[B] such that C[A] is subtype of C[B] then C is said to be covariant
Examples
Immutable List and Queue are examples of covariant Types in scala libraries.
1
2
3
sealed abstract class List[+A] extends .........
class Queue[+A] extends ........
Covariance is indicated by notation + on type parameter passed

Immutablity and Covariance

If you notice in api-docs covariance is generally associated with immutable types , eg scala.collection.immutable.Queue, scala.collection.immutable.List
There is a very good reason for this. From designers perspective, there were 2 reasons where covariance relation could fail
  • Re-Assignment of values. Classic example being java array reassignment problem, resulting in ArrayStore exception
  • Passing generic type as a parameter in method.
Thus to avoid above pitfalls , covariant types are immutable

If you have 2 classes A, B such that A is subtype of B, and
if you have 2 parametrized Types C[A], C[B] such that C[B] is subtype of C[A] then C is said to be contravariant
Examples
OuputChannel trait from scala api is example of contravariant type
1
trait OutputChannel[-Msg] extends AnyRef
Contravariance is indicated by notation – on type parameter passed. 

*** Function parameters are contravariant ***
*** Function’s return value type is covariant ***

https://twitter.github.io/scala_school/type-basics.html
Variance
Scala’s type system has to account for class hierarchies together with polymorphism. Class hierarchies allow the expression of subtype relationships. A central question that comes up when mixing OO with polymorphism is: if T’ is a subclass of T, is Container[T’] considered a subclass of Container[T]? Variance annotations allow you to express the following relationships between class hierarchies & polymorphic types:
MeaningScala notation
covariantC[T’] is a subclass of C[T][+T]
contravariantC[T] is a subclass of C[T’][-T]
invariantC[T] and C[T’] are not related[T]
The subtype relationship really means: for a given type T, if T’ is a subtype, can you substitute it?
scala> class Covariant[+A]
defined class Covariant

scala> val cv: Covariant[AnyRef] = new Covariant[String]
cv: Covariant[AnyRef] = Covariant@4035acf6

scala> val cv: Covariant[String] = new Covariant[AnyRef]
:6: error: type mismatch;
 found   : Covariant[AnyRef]
 required: Covariant[String]
       val cv: Covariant[String] = new Covariant[AnyRef]
                                   ^

No comments: