Scala:将路径独立类型的值分配给路径依赖类型的值

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

我知道,比如Long和路径依赖型foo.Long是不同的类型

但是Scala有没有办法将路径无关类型的值赋值给路径相关类型?

 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
  }

当然,我得到:

type mismatch;
 found   : App.Encoder[Long]
 required: App.Encoder[App.BarImpl.foo.Id]
    override val idEncoder: Encoder[foo.Id] = longIdEncoder

我该如何克服这个问题?

编译器只知道 foo 有一个类型 Foo 但它不知道具体是哪一个。所以你需要通过给 foo 一个更严格的类型来告诉它是哪一个:

object BarImpl extends Bar {
  override val foo: FooImpl.type = FooImpl
  override val idEncoder: Encoder[foo.Id] = longIdEncoder
}

或者不为 foo 指定类型:

override val foo = FooImpl

编译器将为 foo 推断出更严格的类型,然后从更具体的 foo 实例中推断出 idEncoder 作为正确的类型。

另一种方法是使用 asInstanceOf:

强制类型
override val idEncoder: Encoder[foo.Id] = longIdEncoder.asInstanceOf[Encoder[foo.Id]]

但这应该避免。