【问题标题】:Bizzare type inference limitation - multiple type paramsBizzare 类型推断限制 - 多种类型参数
【发布时间】:2015-08-19 13:43:02
【问题描述】:

为什么不编译?

trait Lol[A, SA] {
  def flatMap[B, SB](f: A => Lol[B, SB]): Lol[B, SB] = ???
}

val p1: Lol[Int, String] = ???
val p2: Lol[Double, Nothing] = ???

val p5 = p1.flatMap(_ => p2)

结果:

found   : Int => Lol[Double,Nothing]
required: Int => Lol[Double,SB]
   val p5 = p1.flatMap(_ => p2)
                         ^    

事情开始编译时:

  • flatMap 调用的类型参数是显式的
  • SA 是协变的(wtf?)
  • Nothing 以外的其他类型用于p2(例如Null
  • SB 不会出现在 flatMap 的返回类型中或出现在该返回类型的协变位置(例如返回类型是 Option[SB]

不过,上述解决方法对我来说是不可接受的。

【问题讨论】:

  • 为什么你没有选择方差注释?通常在可能的情况下使用方差是个好主意。大部分时间使用Nothing 只有在方差下才有意义。
  • @0__ SA 在给定完整的 API(此处未显示)的情况下根本无法协变。但是 - 你对Nothing 是正确的 - 如果SA 不是协变的,我可能可以组成我自己的特殊类型而不是使用Nothing
  • 尽管如此,这个错误仍然非常离奇,而且有臭虫的味道。
  • 这可能是一个错误。 Nothing 可能在这里由 scalac 专门处理,因为假设推理失败。如果没有人回答,我建议在issues.scala-lang.org打开一个bug

标签: scala type-inference


【解决方案1】:

@retronym 对SI-9453 的评论解释了您所看到的行为。这是一种解决方法...

我们可以合成一个等价于Nothing的类型,这不会导致打字员撤回推理解决方案,

type ReallyNothing = Nothing { type T = Unit }

即。 Nothing 带有虚拟改进。现在以问题为例,

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Lol[A, SA] {
  def flatMap[B, SB](f: A => Lol[B, SB]): Lol[B, SB] = ???
}

val p1: Lol[Int, String] = ???
val p2: Lol[Double, ReallyNothing] = ???

val p5 = p1.flatMap(_ => p2)

// Exiting paste mode, now interpreting.

scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
  ... 37 elided

【讨论】:

    【解决方案2】:

    为了更好的理解你的问题,可以简化为:

    class Lol[A]
    def foo[B](f: Lol[B]) = f
    foo(new Lol[Nothing])
    

    这会给你以下编译错误:

    error: type mismatch;
     found   : Lol[Nothing]
     required: Lol[B]
    Note: Nothing <: B, but class Lol is invariant in type A.
    You may wish to define A as +A instead. (SLS 4.5)
    

    一种可能的解决方案是像这样更新 sn-p:

    def foo[B <: Lol[_]](f: B) = f
    

    回到你原来的代码:

    trait Lol[A, SA] {
      def flatMap[B <: Lol[_,_]](f: A => B): B = ???
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      相关资源
      最近更新 更多