Search code examples
scalaimplicitvariancepath-dependent-type

Variance trick with path-dependent types


Here's another one for implicits and path dependent types. I don't understand why I need to be so verbose here: (Note -- I found the answer, see below)

trait B
trait C[X]
trait A { def call[B1 <: B](implicit b: B1): C[B1] }
trait D extends B {
  def set(c: C[this.type]): Unit
}

first try:

def test1(a: A)(implicit d: D: Unit =
  d.set(a.call) // found C[D] -- required C[d.type]

second try:

def test2(a: A)(implicit d: D): Unit =
  d.set(a.call[d.type]) // could not find implicit value for parameter b: d.type

third try:

def test3(a: A)(implicit d: D): Unit =
  d.set(a.call[d.type](d))  // works. why so much clutter!?

Solution

  • the Scala 2.9 REPL helps us (thanks, whoever added this useful message!). Here for the test1:

     found   : C[D]
     required: C[d.type]
    Note: D >: d.type, but trait C is invariant in type X.
    You may wish to define X as -X instead. (SLS 4.5)
                  d.set( a.call ) // found C[D] -- required C[d.type]
                           ^
    

    Thus: changing trait C[ X ] to trait C[ -X ] makes test1 work as expected.