Skip to content

Instantly share code, notes, and snippets.

@joprice
Forked from kailuowang/abvsTypeDep.scala
Last active December 21, 2015 22:59
Show Gist options
  • Save joprice/ce4d9f000c285f602aff to your computer and use it in GitHub Desktop.
Save joprice/ce4d9f000c285f602aff to your computer and use it in GitHub Desktop.
Abstract Type vs Type parameter
trait AnimalMouth
class Beak extends AnimalMouth
object Test1 {
//================================Generic type works as in the following =======================
trait Animal[Mouth <: AnimalMouth] {
def mouth : Mouth
def feedAnother(m: Mouth): Unit = ()
}
class Bird extends Animal[Beak] {
def mouth: Beak = new Beak
}
// compiles, but when called with two instances of Bird, gives `type arguments [Mouth] do not conform to trait Animal's type parameter bounds [Mouth <: AnimalMouth]`
//def feed[Mouth <: AnimalMouth, A <: Animal[Mouth]](mother: A, child: A) : Unit = mother.feedAnother(child.mouth)
def feed[Mouth <: AnimalMouth](mother: Animal[Mouth], child: Animal[Mouth]): Unit = mother.feedAnother(child.mouth)
}
//==============Make mouth an abstract type and it would be hard ===========================
object Test2 {
trait Animal {
type Mouth <: AnimalMouth
def mouth : Mouth
def feedAnother(m: Mouth): Unit = ()
}
class Bird extends Animal {
type Mouth = Beak
def mouth: Mouth = new Beak
}
def feed[A <: Animal, B](mother: A { type Mouth = B}, child: A {type Mouth = B} ) : Unit = mother.feedAnother(child.mouth)
}
//=============== Work Around using Aux ================
object Test3 {
trait Animal {
type Mouth <: AnimalMouth
def mouth : Mouth
def feedAnother(m: Mouth): Unit = ()
}
class Bird extends Animal {
type Mouth = Beak
def mouth: Mouth = new Beak
}
object Animal {
type Aux[Mouth0] = Animal { type Mouth = Mouth0 }
}
def feed[Mouth](mother: Animal.Aux[Mouth], child: Animal.Aux[Mouth]) : Unit = mother feedAnother child.mouth
}
object Test {
def main(args: Array[String]): Unit = {
{
import Test1._
val mother = new Bird()
val child = new Bird()
feed(mother, child)
}
{
import Test2._
val mother = new Bird()
val child = new Bird()
feed(mother, child)
}
{
import Test3._
val mother = new Bird()
val child = new Bird()
feed(mother, child)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment