Skip to content

Instantly share code, notes, and snippets.

@sshark
Last active July 5, 2016 16:27
Show Gist options
  • Select an option

  • Save sshark/ea20cbf0c10576af272e to your computer and use it in GitHub Desktop.

Select an option

Save sshark/ea20cbf0c10576af272e to your computer and use it in GitHub Desktop.
Retroactive polymorphism using ducks as example
case class WildDuck() {
def swim = "It swims"
def quack = "Quack quack"
def fly = "If flies"
}
case class RubberDuck() {
def quacky = "Quackkkkk...."
}
trait DuckLike[A] {
def quack(duck: A): Option[String]
def swim(duck: A): Option[String]
def fly(duck: A): Option[String]
}
def cook[A: DuckLike](duck: A): Option[(String, String, String)] = {
val duckLike = implicitly[DuckLike[A]]
for {
quack <- duckLike.quack(duck)
swim <- duckLike.swim(duck)
fly <- duckLike.fly(duck)
} yield (quack, swim, fly)
}
def eat(x: Option[(String, String, String)]) = x match {
case Some(_) => "Yeah, tasty Peking duck"
case _ => "Nah!!! It's a fake"
}
implicit object CookWildDuck extends DuckLike[WildDuck] {
override def swim(duck: WildDuck) = Some(duck.swim)
override def quack(duck: WildDuck) = Some(duck.quack)
override def fly(duck: WildDuck) = Some(duck.fly)
}
eat(cook(WildDuck()))
implicit object CookRubber extends DuckLike[RubberDuck] {
override def swim(duck: RubberDuck) = None
override def quack(duck: RubberDuck) = Some(duck.quacky)
override def fly(duck: RubberDuck) = None
}
eat(cook(RubberDuck()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment