微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

scala – 为什么不在此处键入推理?

这个问题出现在我正在编写的模块中,但我做了一个表现出相同行为的最小案例.

class Minimal[T](x : T) {
  def doSomething = x
}

object Sugar {
  type S[T] = { def doSomething : T }
  def apply[T,X <: S[T]] (x: X) = x.doSomething
}

object Error {
  val a = new Minimal(4)
  Sugar(a) // error: inferred [nothing,Minimal[Int]] does not fit the bounds of apply
  Sugar[Int,Minimal[Int]](a) // works as expected
}

问题是编译器设法找出Minimal(Int)的内部参数,但是然后将T的另一个出现设置为nothing,这显然与apply不匹配.这些肯定是相同的T,因为删除一个参数使第二个抱怨T未定义.

是否有一些含糊不清意味着编译器无法推断出第一个参数,或者这是一个错误?我可以优雅地解决这个问题吗?

更多信息:此代码是尝试语法糖的简单示例.原始代码尝试制作|(a)|表示a的模数,其中a是矢量.显然|(a)|比写[| Float,Vector3 [Float]](a)|更好,但不幸的是我不能使用unary_ |使这更容易.

实际错误

inferred type arguments [nothing,Minimal[Int]] do not conform to method apply’s type parameter bounds [T,X <: Sugar.S[T]]

解决方法

这不是Scala编译器错误,但它肯定是Scala类型推断的限制.在解决X之前,编译器想要确定X,S [T]上的边界,但是绑定提到了迄今为​​止无约束的类型变量T,因此它固定在nothing并从那里继续.一旦X完全解析,它就不会重新审视T …在这种情况下,当前类型推断总是从左到右进行.

如果您的示例准确地表示您的实际情况,那么有一个简单的修复,

def apply[T](x : S[T]) = x.doSomething

这里将推断T,使得Minimal直接符合S [T]而不是通过中间有界类型变量.

更新

约书亚的解决方案也避免了推断类型T的问题,但是以完全不同的方式.

def apply[T,X <% S[T]](x : X) = x.doSomething

desugars,

def apply[T,X](x : X)(implicit conv : X => S[T]) = x.doSomething

现在可以独立地求解类型变量T和X(因为在X的界限中不再提及T).这意味着X立即被推断为Minimal,并且T被解析为隐式搜索类型X =>的值的一部分. S [T]满足隐式参数conv. scala中的conform.Predef制造这种形式的值,并且在上下文中将保证给定Minimal类型的参数,T将被推断为Int.您可以在Scala中将其视为functional dependencies的实例.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐