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

问题描述

我知道,例如,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]]

但这应该避免。