scala - 为什么在没有子类型证据的情况下,这个多函数案例的隐式推导会失败?

标签 scala type-inference implicit generic-programming shapeless

下面的示例中有两个类似的无形状多态函数。它们之间唯一的区别是deserSucceeding的隐式案例定义有一个额外的子类型证据 (implicit e: FS <: FromStr[T]) 。 Scala 无法导出隐式 Aux.Case对于 deserFailing ,但成功 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]]编译器尝试以相同的类型推断两者,因此它最终可能会从其中之一推断任何,以使子类型约束进行类型检查。< br/> 而第二个选项在推理过程中不会强制任何子类型限制,这使得编译器能够推断出更好的类型,然后它将检查子类型约束。

与此示例类似:

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 .

关于scala - 为什么在没有子类型证据的情况下,这个多函数案例的隐式推导会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65492976/

相关文章:

scala - Slick:过滤所有 joda DateTime 日期等于今天的记录

scala - Spark 案例类 - 十进制类型编码器错误 "Cannot up cast from decimal"

javascript - 显式类型传递是否不等同于类型推断(就表达能力而言)?

haskell - 刚性类型变量麻烦/可疑

c# - 由于泛型类型推断的限制,无法使用泛型来改进 API

scala - 将现有变量标记为隐式方法的候选者

scala - 为什么有从 Float/Double 到 BigDecimal 的隐式转换,而不是从 String 的隐式转换?

scala - 在 Scala 中的对象成员上使用 private[this]

scala - 了解 NotUsed 和 Done

Scala - 隐式类中的重载方法