implicit extension methods on type refinements

125 views Asked by At

I seem to be unable to get implicit extension methods to work with type refinements, in scala 2.12.4. Consider the following:

trait MyTypeclass[A,B] {
  def foo[C](a : Test.Aux[A,B], c : C ) : Test.Aux[A,C]
}

object MyTypeclass {
  trait Ops[A,B] {
    def instance : MyTypeclass[A,B]
    def self : Test.Aux[A,B]
    def foo[C](c : C) : Test.Aux[A,C] = instance.foo[C](self,c)
  }

  object syntax {
    def toAllOps[A,B](t : Test.Aux[A,B])(implicit tc : MyTypeclass[A,B]) = new Ops[A,B] {
      val instance = tc
      val self = t
    }
  }
}

trait Test[A] {
  type B
}

object Test {

  type Aux[A,B0] = Test[A] { type B = B0 }

  def apply[A,B0] : Aux[A,B0] = new Test[A] { type B = B0 } 

  implicit def instance[A,B] : MyTypeclass[A,B] = new MyTypeclass[A,B] { 
    /** Does nothing more than change the second type `B` to the passed value `C` */
    def foo[C](a : Test.Aux[A,B], c : C) : Test.Aux[A,C] = new Test[A] { type B = C }
  }

  import MyTypeclass.syntax.toAllOps
  toAllOps(Test[String,Int]).foo(2.0)
  //Test[String,Int].foo(2.0) // ERROR : `foo is not a member of Test.Aux[String,Int]`
}

The penultimate line works fine, but the last line doesn't. The compiler for some reason is unable to link up the typeclass extension methods with the Aux.

Can somebody explain why this is?

1

There are 1 answers

2
Jasper-M On BEST ANSWER

Because toAllOps is not implicit.