Consider the following piece of code:
trait Foo {
type T
def value: T
}
object Foo {
def apply[A](v: A): Foo = new Foo {
override type T = A
override def value = v
}
}
trait Decode[A] {
def apply(x: A): String
}
object Decode {
def apply[A](f: A => String): Decode[A] = new Decode[A] {
override def apply(x: A) = f(x)
}
implicit val decodeStr: Decode[String] = Decode(identity)
}
class Sandbox {
def decodeFoo(foo: Foo)(implicit decoder: Decode[foo.T]): String =
decoder(foo.value)
val foo = Foo("hello")
println(decodeFoo(foo))
}
The above code should work fine and print hello but instead it fails to compile:
could not find implicit value for parameter decoder: Decode[Sandbox.this.foo.T]
[error] println(decodeFoo(foo))
Even when I explicitly pass in the implicit param:
println(decodeFoo(foo = foo)(decoder = Decode.decodeStr))
I still get this error now:
type mismatch;
[error] found : Decode[String]
[error] required: Decode[Sandbox.this.foo.T]
[error] println(decodeFoo(foo = foo)(decoder = Decode.decodeStr))
[error] ^
Ofcourse, I can make Foo a Foo[T] and define decoders for it but that's not the point of this question - I want to understand why the above code fails to compile.
The problem exists here:
There, you've established that you will return a
Foobut not, specifically, whichFoo. Hence, that function only knows that it can return aFoofor any typeT. You need anAuxpattern to recapture the type which is lost when establishing your newFoo(yes, yes...)which then says that for a given
Aproduce theFoowhich has it'sTdependent type set toA.