I know that, for example, Long
and path-dependent type foo.Long
are different types.
But is there a way in Scala to assign the value of path-independent type to path-dependant one?
trait Encoder[T] {
def encode(v: T): String
}
val longIdEncoder: Encoder[Long] = (v: Long) => s"${v.toString} !!!"
trait Foo {
type Id
val id: Id
}
trait Bar {
val foo: Foo
val idEncoder: Encoder[foo.Id]
}
object FooImpl extends Foo {
override type Id = Long
override val id: Long = 10
}
object BarImpl extends Bar {
override val foo: Foo = FooImpl
override val idEncoder: Encoder[foo.Id] = longIdEncoder // <-- Error
}
Of course, I'm getting:
type mismatch;
found : App.Encoder[Long]
required: App.Encoder[App.BarImpl.foo.Id]
override val idEncoder: Encoder[foo.Id] = longIdEncoder
How can I overcome this?
The compiler only knows foo
has a type Foo
but it does not know explicitly which one. So you need to tell it which one by giving foo
a more strict type:
object BarImpl extends Bar {
override val foo: FooImpl.type = FooImpl
override val idEncoder: Encoder[foo.Id] = longIdEncoder
}
Or just don't specify a type for foo:
override val foo = FooImpl
The compiler will infer a more strict type for foo
then deduce the idEncoder
as the proper type from the more specific foo instance.
Another way is to force the type using asInstanceOf
:
override val idEncoder: Encoder[foo.Id] = longIdEncoder.asInstanceOf[Encoder[foo.Id]]
But this should be avoided.