所以我花了点时间,试着写一些关于存在性和方差的东西,我偶然发现了这段有趣的代码。
final case class Box[+T](val value: T) {
def >>=[U](f: T => Box[U]) = f(value)
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
}这无法编译:
Variance.scala:3: no type parameters for method >>=: (f: T => Box[U])Box[U] exist so that it can be applied to arguments (_$1 => _$2)
--- because ---
argument expression's type is not compatible with formal parameter type;
found : _$1 => _$2 where type _$2 <: Box[_ <: U], type _$1 >: T
required: T => Box[?U]
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
^
Variance.scala:3: type mismatch;
found : _$1 => _$2 where type _$2 <: Box[_ <: U], type _$1 >: T
required: T => Box[U]
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
^我觉得这很奇怪,因为(_ >: T) => (_ <: Box[_ <: U])不是T => Box[U]的一个子类型吗?因为第一个类型参数中的Function1是逆变量,所以这是T => (_ <: Box[_ <: U])的一个子类型。由于Function1在结果类型中是协变的,这是T => Box[_ <: U]的一个子类型,而由于Box在其参数中是协变的,所以整个事物不是T => Box[U]的子类型吗
奇怪的是,将代码更改为
// This change is not required ;)
type Box[T] = `What A Category Theorist Calls "The Identity Monad" And What Everyone Else Calls "A Box"`[T]
final case class `What A Category Theorist Calls "The Identity Monad" And What Everyone Else Calls "A Box"`[+T](val value: T) {
def >>=[U](f: T => Box[U]) = f(value)
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= (f: T => Box[U])
}使用类型归属来“提示”编译器f: T => Box[U]使其进行编译。既然这里没有隐式转换或变量声明,这不应该没有区别吗?
我发现的另一种编译方法是编写
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this.>>=[U](f)这让我相信,问题并不在于编译器很难获得(_ >: T) => (_ <: Box[_ <: U]) <: T => Box[U],而在于它无法推断出>>=的类型参数,这似乎就是错误消息所暗示的。
(使用Scala 2.12.1 (使用sbt,如果有任何改变))
发布于 2017-06-26 15:35:28
final case class Box[+T](val value: T) {
def >>=[U](f: T => Box[U]) = f(value)
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
}flatMap返回类型为Box[U],但要使用this >>= f。
因此,>>=将自动更改为f类型(_ >: T) => (_ <: Box[_ <: U])。
因此Box[(_ >: T) => (_ <: Box[_ <: U])]与Box[U]不匹配。
我认为你可以像这样改变:
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>=[U] f
https://stackoverflow.com/questions/41213696
复制相似问题