【问题标题】:Why does the implicit derivation of this poly function case fails without subtype evidence?为什么在没有子类型证据的情况下,这种多函数情况的隐式推导会失败?
【发布时间】:2021-04-06 03:09:45
【问题描述】:

以下示例中有两个类似的无形多态函数。它们之间的唯一区别是deserSucceeding 的隐式案例定义有一个额外的子类型证据(implicit e: FS <: FromStr[T])。 Scala 无法为deserFailing 导出隐式Aux.Case,但为deserSucceeding 成功。

为什么?这是 scala 编译器的限制还是 deserSucceeding 会导致隐式推导/类型推断中的歧义?

import shapeless._
type FromStr[T] = String => T
object FromDouble extends FromStr[Double] {
  override def apply(v1: String): Double = v1.toDouble
}

object deserFailing extends Poly2 {
  implicit def kase[T, FS <: FromStr[T]]: Case.Aux[String, FS, T] = at((s, fs) => fs(s))
}
// fails to derive a `Case.Aux`
deserFailing("1.0", FromDouble)

object deserSucceeding extends Poly2 {
  implicit def kase[T, FS](implicit e: FS <:< FromStr[T]): Case.Aux[String, FS, T] = at((s, fs) => fs(s))

}
deserSucceeding("1.0", FromDouble)

【问题讨论】:

    标签: scala type-inference implicit generic-programming shapeless


    【解决方案1】:

    TL;DR;这就是类型推断的工作原理。

    当您执行[T, FS &lt;: FromStr[T]] 时,编译器会尝试以相同的类型推断两者,因此它可能最终会从其中一个推断出 AnyNothing类型检查的子类型约束。
    而第二个选项在推理过程中不会强制任何子类型限制,这使得编译器可以推断出更好的类型,然后它会检查子类型约束。

    和这个例子类似:

    def tupleIfSubtype1[T <: U, U](t: T, u: U) = (t, u)
    def tupleIfSubtype2[T, U](t: T, u: U)(implicit ev: T <:< U) = (t, u)
    
    tupleIfSubtype1("Foo", 3) // compiles, it infers Any for the second element.
    tupleIfSubtype2("Foo", 3) // doesn't compile.
    

    更深入的解释,here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多