Search code examples
scalatypestype-parameter

Can we use the singleton .type as a type parameter?


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?


Solution

  • 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