Skip to content

Instantly share code, notes, and snippets.

@aris-vlasakakis-ck
Created June 19, 2017 23:59
Show Gist options
  • Save aris-vlasakakis-ck/d719e49e3e0e2dcd3e5b72fa37bf2c14 to your computer and use it in GitHub Desktop.
Save aris-vlasakakis-ck/d719e49e3e0e2dcd3e5b72fa37bf2c14 to your computer and use it in GitHub Desktop.
case class Dog()
case class Cat()
case class Human()
trait Talks[A] {
def talk(x: A): String
}
implicit val dogTalks = new Talks[Dog] {
def talk(x: Dog): String = "gav gav"
}
implicit val catTalks = new Talks[Cat] {
def talk(x: Cat): String = "niao niao"
}
implicit val humanTalks = new Talks[Human] {
def talk(x: Human): String = "awesome dude"
}
implicit class TalksSyntax[A](value: A) {
def talk(implicit T: Talks[A]): String = T.talk(value)
}
def listTalk[A: Talks](l: List[A]): List[String] = {
l.map(i => i.talk)
}
val h = Human()
h.talk
val c = Cat()
c.talk
val d = Dog()
d.talk
//this works fine, compiles and runs
listTalk(List(h, h, h))
//TODO does not compile!
listTalk(List(h, c, d))
@aris-vlasakakis-ck
Copy link
Author

So there is a surprising solution to getting the listTalk polymorphic method/function to actually work, not using HList or cheating with sub-classing.

Are these the best solution?

implicit class TalksSyntax[A : Talks](value: A) {
  def talk: String = implicitly[Talks[A]].talk(value)
}

def listTalk(l: List[TalksSyntax[_]]): List[String] =
  l.map{_.talk}

//this works now, but it requires an explicit type for `lst`
val lst: List[TalksSyntax[_]] = List(h, c, d)

also equivalently for listTalk the signature can be as follows:

def listTalk[A <: TalksSyntax[_]](l: List[A]): List[String] 

...but you notice the second form of the signature uses the <: type bounds in a way that almost suggests we are using sub-classing, but I guess we are only "constraining" the type in a hierarchic fashion to make sure it is a TalksSyntax or some subclass.

I guess this works? Is it the idiomatic way to do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment