这个问题出现在我正在编写的模块中,但我做了一个表现出相同行为的最小案例。
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(使用前将#替换为@)