首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么编译器找不到V[+_]的(_ >:T) => (_ <:V[_ <:U]) <:t => V[U]?

为什么编译器找不到V[+_]的(_ >:T) => (_ <:V[_ <:U]) <:t => V[U]?
EN

Stack Overflow用户
提问于 2016-12-19 06:48:16
回答 1查看 200关注 0票数 4

所以我花了点时间,试着写一些关于存在性和方差的东西,我偶然发现了这段有趣的代码。

代码语言:javascript
运行
复制
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
}

这无法编译:

代码语言:javascript
运行
复制
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]的子类型吗

奇怪的是,将代码更改为

代码语言:javascript
运行
复制
// 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]使其进行编译。既然这里没有隐式转换或变量声明,这不应该没有区别吗?

我发现的另一种编译方法是编写

代码语言:javascript
运行
复制
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this.>>=[U](f)

这让我相信,问题并不在于编译器很难获得(_ >: T) => (_ <: Box[_ <: U]) <: T => Box[U],而在于它无法推断出>>=的类型参数,这似乎就是错误消息所暗示的。

(使用Scala 2.12.1 (使用sbt,如果有任何改变))

EN

回答 1

Stack Overflow用户

发布于 2017-06-26 15:35:28

代码语言:javascript
运行
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41213696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档