scalapath-dependent-type

Scala: Assign the value of path-Independent type to value of path-Depended type


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?


Solution

  • 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.