为什么在没有子类型证据的情况下,这个多函数案例的隐式推导会失败?
Why does the implicit derivation of this poly function case fails without subtype evidence?
下面的例子中有两个相似的无形多态函数。它们之间的唯一区别是 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)
TL;DR;这就是类型推断的工作原理。
当您执行 [T, FS <: FromStr[T]]
时,编译器会尝试以相同类型推断两者,因此它可能最终推断出 Any 或 Nothing 从其中一个使子类型约束进行类型检查。
而第二个选项在推理期间不强制任何子类型限制,这使得编译器推断出更好的类型,然后它将检查子类型约束。
类似于这个例子:
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。
下面的例子中有两个相似的无形多态函数。它们之间的唯一区别是 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)
TL;DR;这就是类型推断的工作原理。
当您执行 [T, FS <: FromStr[T]]
时,编译器会尝试以相同类型推断两者,因此它可能最终推断出 Any 或 Nothing 从其中一个使子类型约束进行类型检查。
而第二个选项在推理期间不强制任何子类型限制,这使得编译器推断出更好的类型,然后它将检查子类型约束。
类似于这个例子:
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。