【发布时间】: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 => if(x % 2 == 0) Full(x) else Empty() 的参数类型推断类型参数。怎么了?我听说Product 和Serializable 自动混入到case 类中,所以上面的函数字面量的类型是Int => Product with Serializable with A$A22.this.Maybe[_ <: Int],如错误消息所示。这与问题有关吗?
【问题讨论】:
标签: scala