Skip to content

Instantly share code, notes, and snippets.

@TobiasRoland
Created July 31, 2020 09:01
Show Gist options
  • Save TobiasRoland/b29c10763c993c5b2caf682801b1e2bb to your computer and use it in GitHub Desktop.
Save TobiasRoland/b29c10763c993c5b2caf682801b1e2bb to your computer and use it in GitHub Desktop.
import WhyIsContravarianceSoHard.{Animal, Cat, Dog, Vet}
object WhyIsContravarianceSoHard extends App {
//why are contravariance so hard
val list: List[Int] = List(1, 2, 3)
class Animal
class Dog(name: String) extends Animal
class Cat(name: String) extends Animal
//Question: if Dog <: Animal does List[Dog] <: List[Animal]? THE VARIANCE QUESTION.
//if YES, then the type is called COVARIANT
val lassie = new Dog("lassie")
val hachi = new Dog("hachi")
val laika = new Dog("laika")
val anAnimal: Animal = lassie // dog
val myDogs: List[Animal] = List(lassie, hachi, laika) // list of dogs is a list of animals
//if NO, then the type is called INVARIANT - default
class MyInvariantList[T]
//val myDogsInvariant: MyInvariantList[Animal] = new MyInvariantList[Dog]
val myDogsInvariant: MyInvariantList[Animal] = new MyInvariantList[Animal]
//HELL NO, or No, quite the opposite - CONTRAVARIANCE
class MyContravarianceList[-T]
val myContravarianceDogs: MyContravarianceList[Dog] = new MyContravarianceList[Animal] // ?!
// a contravariance example
trait Vet[-T <: Animal]{
def heal(animal: T): Boolean
}
val myDog = new Dog("buddy")
val myDogVet:Vet[Dog] = VetStation.gimmeADogVet()
myDogVet.heal(myDog)
val myCat = new Cat("catter")
val myCatVet:Vet[Cat] = VetStation.gimmeACatVet()
myCatVet.heal(myCat)
//contains or creates elements of type T, it should be +T
//acts on or consumes elements of type T, it should be -T
//covariant concepts: a cage, a garage, a factory, a list
//contravariant concepts: a vet, a mechanic, a garbage pit, a function (in terms of arg type)
}
object VetStation {
def gimmeADogVet(): Vet[Dog] = new Vet[Animal] {
override def heal(animal: Animal): Boolean = true
}
def gimmeACatVet(): Vet[Cat] = new Vet[Animal] {
override def heal(animal: Animal): Boolean = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment