【问题标题】:Inferring type parameter of method from method argument fails in Scala?: "no type parameters for method"从方法参数推断方法的类型参数在 Scala 中失败?:“方法没有类型参数”
【发布时间】:2017-08-18 23:22:42
【问题描述】:

这个例子取自 Underscore.io 的“Essential Scala”练习。 以下是代数和类型Maybe[A] 的定义,它模仿了Option[A] 的一些基本特征和Maybe[Int] 的列表。

sealed trait Maybe[A] {
  def flatMap[B](fn: A => Maybe[B]): Maybe[B] =
    this match {
      case Full(v) => fn(v)
      case Empty() => Empty[B]()
    }

  def map[B](fn: A => B): Maybe[B] =
    this match {
      case Full(v) => Full(fn(v))
      case Empty() => Empty[B]()
    }
}
final case class Full[A](value: A) extends Maybe[A]
final case class Empty[A]() extends Maybe[A]

val list = List(Full(3), Full(2), Full(1))

我尝试用 Empty[Int] 将 list 中的元素替换为奇数,因此通过以下语句得到 List(Empty(), Full(2), Empty())

list.map(maybe => maybe flatMap { x => if(x % 2 == 0) Full(x) else Empty() })

这和书上的答案完全一样。

但我得到了一个错误:

Error:(41, 26) no type parameters for method flatMap: (fn: Int => A$A22.this.Maybe[B])A$A22.this.Maybe[B] exist so that it can be applied to arguments (Int => Product with Serializable with A$A22.this.Maybe[_ <: Int])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : Int => Product with Serializable with A$A22.this.Maybe[_ <: Int]
 required: Int => A$A22.this.Maybe[?B]
list.map(maybe => maybe flatMap { x => if(x % 2 == 0) Full(x) else Empty() })
                        ^

所以我写了类型参数然后效果很好:

list.map(maybe => maybe flatMap[Int] { x => if(x % 2 == 0) Full(x) else Empty() })

我认为即使不提供类型参数 Int 也可以,因为似乎可以从 flatMap x =&gt; if(x % 2 == 0) Full(x) else Empty() 的参数类型推断类型参数。怎么了?我听说ProductSerializable 自动混入到case 类中,所以上面的函数字面量的类型是Int =&gt; Product with Serializable with A$A22.this.Maybe[_ &lt;: Int],如错误消息所示。这与问题有关吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    问题是Empty():编译器没有理由为它选择除Nothing 之外的任何类型参数(特别是,它不查看if 的其他分支)。所以它在一个分支中以Full[Int] 结尾,在另一个分支中以Empty[Nothing] 结尾,它们的常见类型是Product with Serializable with Maybe[_ &lt;: Int],如错误消息所示。从 this 结果类型,显然无法推断出flatMap 的类型参数。

    当定义一个只能由案例类扩展的特征时,包含trait Maybe[A] extends Product with Serializable 是很正常的,因此它们将被包含在这样的上限计算中,但你仍然会得到Maybe[_ &lt;: Int](如果你不熟悉这种表示法,它的意思是“Maybe,其类型参数是Int 的某个子类型”):编译器注意到Full[Int]Maybe[Int] 的子类型,而Empty[Nothing]Maybe[Nothing] 的子类型,但Maybe[Nothing] 不是Maybe[Int] 的子类型。

    我希望您会在接下来的练习中看到解决问题的更好方法,但目前的解决方法是指定 Empty[Int]()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      相关资源
      最近更新 更多