简体   繁体   English

为什么 Scala 类型推断在这里失败

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM