Skip to content

Instantly share code, notes, and snippets.

@nsfyn55
Last active October 13, 2015 04:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nsfyn55/4141034 to your computer and use it in GitHub Desktop.
Save nsfyn55/4141034 to your computer and use it in GitHub Desktop.
Contravariance Example
/*
Invariant:
String is subclass of Object but in java
List<String> is not a subclass of List<Object>
Covariant
String in scala is a subclass of Object
List[String] is a subclass of List[Object]
Contravariant
Will accept types that are super classes of
the proposed type.
class X[-A]
val x: X[String] = new X[Object]
*/
//cool, but why:
/*** Covariant FAIL ***/
class Output[+A]{def write(a:A) = /* Do some writing */}
def writeObject(out: Output[Object]) = out.write("hello")
/*
The code below fails because as defined it only
accepts types covariant to List[String]. The call to
"write" attempts to pass a Object[Object] which is
itself covariant to Output[List[String]] but its the
call write that fails because the type passed is defined
as Output[List[String]] and you are attempting to pass
it a String.
Right now we have this resolution:
writeObject(accepts anything covariant to Object)
write(accepts anything covariant to List[String])
*/
writeObject(new Output[List[String]])
/********************/
/** Contravariant Solution ***/
class Output[-A]{def write(a:A) = /* Do some writing */}
def writeObject(out: Output[Object]) = out.write("hello")
//This now causes type mismatch
//writeObject(new Output[List[String]])
writeObject(new Output[Any])
/*
This now works because write will accept any object that is a
super class of Object and write accepts anything of type a
so you end up with this resolution:
writeObject(accepts anything that is a supertype to Object)
write(accepts anything that is a supertype to Object)
*/
/******************************/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment