【问题标题】:How to make Scala type inference powerful enough to discover generic type parameter?如何使 Scala 类型推断功能强大到足以发现泛型类型参数?
【发布时间】:2016-06-18 19:23:58
【问题描述】:

假设我定义了一个采用隐式 TypeTag 的函数:

  def andOptionFn[A: TypeTag](g: Int => Option[A]) = {
    val ttg = ScalaReflection.universe.typeTag[A]
    println(ttg)
    ...
  }

并称它为:

andOptionFn{
v =>
  Some(v)
}

我希望 scala 类型推断能够获得正确的类型 TypeTag(Option(Int)),但我得到了:

TypeTag(Option(Any)) (not even a higher kind)

为什么 Scala 不能在编译时自动推断它?以及需要做哪些工作来改进它?

【问题讨论】:

    标签: scala type-inference type-erasure


    【解决方案1】:

    正确的结果是TypeTag[Int],Scala 确实打印了它:http://scastie.org/20273(在将ScalaReflection 替换为scala.reflect.runtime 之后;如果ScalaReflection 是您自己的类,那么您应该在那里寻找问题) .

    编辑:http://scastie.org/20293 不是错误,它的类型推断行为与设计完全一致。调用Seq.apply[Option[_]] 会为每个参数提供Option[_] 的预期类型。当

    andOptionFn {
      v =>
        if (v > 1) Some(v)
        else None
    }
    

    用这个预期的类型进行类型检查,推断的R当然是Any

    编辑 2:在更仔细地阅读 http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference 之后,它似乎确实应该推断出 Int,但我不确定。我的想法是Option[_] 被简化为Option[Any](因为Option 是协变的),在这种情况下Any 肯定应该被推断出来。但是http://scastie.org/20293http://scastie.org/20295 应该表现相同,所以至少有一个错误(我认为):)

    【讨论】:

    • 对不起,我遇到的问题确实是由其他原因引起的:它是编译器类型推断中的一个错误,仍未解决:请参阅scastie.org/20293 中的结果一瞥
    • 为了比较,请参阅 2 个略有不同的案例:scastie.org/20294scastie.org/20295
    • 问题是由 andOptionFn 被包装在另一个采用泛型类型参数的函数中引起的。非常复杂的错误对吧?
    • scastie.org/20295, Seq.apply[Option[_]] 怎么没有清除类型? scastie.org/20297 中的 Seq.apply[Option[Any]] 怎么样?尚未阅读规范,但语言设计的重点是简单性和一致性吗?
    • 是的,我同意它们应该是一致的。但是在所有这些情况下始终推断Any 会很好(IMO)。无论如何,我建议在 scala-user 邮件列表中询问或在 issues.scala-lang.org 报告不一致之处。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多