为什么类型推断在这里不起作用?

2024-01-07

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

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 to Nothing,这显然不匹配apply。这些绝对是一样的T,因为删除第一个参数会使第二个参数抱怨 T 未定义。

是否存在一些歧义,意味着编译器无法推断第一个参数,或者这是一个错误?我可以优雅地解决这个问题吗?

更多信息:此代码是尝试语法糖的简单示例。原始代码试图使|(a)|表示模数a,其中 a 是向量。清楚地|(a)|比写作更好|[Float,Vector3[Float]](a)|,但不幸的是我不能使用unary_|让这变得更容易。

实际错误:

推断的类型参数 [Nothing,Minimal[Int]] 不符合方法 apply 的类型参数界限 [T,X <: sugar.s>


这不是 Scala 编译器错误,但它肯定是 Scala 类型推断的限制。编译器想要确定上的界限X, S[T],在求解之前X,但边界提到了迄今为​​止不受约束的类型变量T因此它固定在Nothing并从那里收益。它不会重访T once X已完全解决...目前在这种情况下类型推断总是从左到右进行。

如果您的示例准确地代表了您的真实情况,那么有一个简单的修复方法,

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

Here T将被推断为Minimal符合S[T]直接而不是通过中间有界类型变量。

Update

Joshua的解决方案也避免了推断类型的问题T,但以完全不同的方式。

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

脱糖,

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

类型变量T and X现在可以独立求解(因为T中不再提及X的绑定)。这意味着X被推断为Minimal立即,并且T作为对类型值的隐式搜索的一部分来解决X => S[T]满足隐式论证conv. conforms in scala.Predef产生这种形式的值,并且在上下文中将保证给定类型的参数Minimal, T将被推断为 Int。您可以将此视为一个实例函数依赖 http://www.chuusai.com/2011/07/16/fundeps-in-scala/在 Scala 工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么类型推断在这里不起作用? 的相关文章

随机推荐