I was cobbling together an answer to this question: Scala mixin to class instance, where I showed a way of "mixing-in" another trait or class instance to an existing instance:
case class Person(name: String)
val dave = Person("Dave")
val joe = Person("Joe")
trait Dog { val dogName: String }
val spot = new Dog { val dogName = "Spot" }
implicit def daveHasDog(p: dave.type) = spot
dave.dogName //"Spot"
joe.dogName //error: value dogName is not a member of Person
So after the local implicit def, dave
can effectively be used as a Person with Dog
. My question is, if we wanted to define a method that takes a Person
instance only where the Person
has a Dog
, how do we do it?
I can define a method such as
def showDog(pd: Person with Dog) = pd.name + " shows " + pd.dogName
however this is no good for dave
since he is still just a Person
, despite his implicit transformation abilities.
I tried defining
trait Dog [T] { val dogName: String }
val spot = new Dog [dave.type] { val dogName = "Spot" }
def showDog(p: Person)(implicit dog: Dog[p.type]) = ...
but this is not legal, giving error: illegal dependent method type
. Any ideas?
If you compile with -Ydependent-method-types
, your original code will work with this definition of showDog
:
scala> def showDog(p: Person)(implicit ev: p.type => Dog) = p.name + " shows " + p.dogName
showDog: (p: Person)(implicit ev: p.type => Dog)java.lang.String
scala> showDog(dave)
res1: java.lang.String = Dave shows Spot