[英]Why does Scala type inferencing fail here
Why do right-associative operators have issues with generic-typed functions, even though equivalent left-associative operators work just fine.为什么右关联运算符对泛型函数有问题,即使等效的左关联运算符工作得很好。
implicit class FunctionWrapper[T1, T2](func: T1 => T2) {
def >>>[T3](funcAfter: T2 => T3): T1 => T3 = {
func andThen funcAfter
}
def >>:[T0](funcBefore: T0 => T1): T0 => T2 = {
funcBefore andThen func
}
}
Following are the functions to be chained:以下是要链接的函数:
def intToFloat = Int.int2float _
def floatToString = (_: Float).toString
def identityF[T] = identity(_: T)
As expected, both operators work well with concrete-typed functions:正如预期的那样,这两个运算符都可以很好地处理具体类型的函数:
scala> (intToFloat >>> floatToString)(11)
res5: String = 11.0
scala> (intToFloat >>: floatToString)(11)
res6: String = 11.0
However, the >>: fails with generic-typed functions for some reason:但是,由于某种原因, >>: 使用泛型函数失败:
scala> (intToFloat >>> identityF >>> floatToString)(11)
res7: String = 11.0
scala> (intToFloat >>: identityF >>: floatToString)(11)
<console>:16: error: type mismatch;
found : Nothing => Nothing
required: T0 => Float
(intToFloat >>: identityF >>: floatToString)(11)
^
There are workarounds for this, one being有解决方法,一个是
(intToFloat >>: (identityF (_: Float)) >>: floatToString)(11)
but it seems easy to infer the type of identityF in the given context, why does it fail?但是在给定的上下文中推断identityF的类型似乎很容易,为什么会失败?
When you have a right-associative operator, remember it's really当你有一个右结合运算符时,记住它真的是
floatToString.>>:(identityF).>>:(intToFloat)
Since there is no type parameter given for identityF
, it's governed by local type inference rules.由于没有为identityF
类型参数,因此它受本地类型推断规则的约束。 In this case it tries to find identityF
's type parameter first (I think, but the other way around runs into trouble as well);在这种情况下,它首先尝试找到identityF
的类型参数(我认为,但反过来也会遇到麻烦); because >>:
's type parameter is still unknown, it doesn't know the argument type of the function.因为>>:
的类型参数仍然未知,它不知道函数的参数类型。 It gives up by inferring Nothing
and then fails to find a suitable type parameter for >>:
.它通过推断Nothing
而放弃,然后无法为>>:
找到合适的类型参数。
With andThen
or >>>
, Scala knows expected argument type for identityF
already and so can infer the correct type parameter.使用andThen
或>>>
,Scala 已经知道identityF
预期参数类型,因此可以推断出正确的类型参数。
That is, the problem isn't that >>:
is right-associative, it's the asymmetry between argument and return types.也就是说,问题不在于>>:
是右结合的,而是参数和返回类型之间的不对称。 If you define >>:[T0](f: T1 => T0)
it'll work fine.如果你定义>>:[T0](f: T1 => T0)
它会正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.