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

标签 scala generics functional-programming type-inference

为什么右关联运算符在使用泛型类型函数时会出现问题,尽管等效的左关联运算符工作得很好。

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
  }
}

以下是要链接的函数:

def intToFloat = Int.int2float _
def floatToString = (_: Float).toString
def identityF[T] = identity(_: T)

正如预期的那样,两个运算符都可以很好地处理具体类型的函数:

scala> (intToFloat >>> floatToString)(11)
res5: String = 11.0

scala> (intToFloat >>: floatToString)(11)
res6: String = 11.0

但是,由于某种原因, >>: 无法使用泛型类型函数:

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)
                                 ^

对此有一些解决方法,其中之一是

(intToFloat >>: (identityF (_: Float)) >>: floatToString)(11)

但是在给定上下文中推断identityF的类型似乎很容易,为什么会失败?

最佳答案

当你有一个右结合运算符时,请记住它实际上是

floatToString.>>:(identityF).>>:(intToFloat)

由于没有为 identityF 提供类型参数,因此它受 local type inference 控制规则。在这种情况下,它会尝试首先找到 identityF 的类型参数(我认为,但反过来也会遇到麻烦);因为 >>: 的类型参数仍然未知,它不知道函数的参数类型。它通过推断 Nothing 放弃,然后无法为 >>: 找到合适的类型参数。

使用 andThen>>>,Scala 已经知道 identityF 的预期参数类型,因此可以推断出正确的类型参数。

也就是说,问题不在于 >>: 是右关联的,而是参数和返回类型之间的不对称。如果您定义 >>:[T0](f: T1 => T0) 它将正常工作。

关于scala - 为什么 Scala 类型推断在这里失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42055521/

相关文章:

scala - 在Scala中将null转换为Int和Double

scala - Spark错误: executor. CoarseGrainedExecutorBackend:收到信号术语

android - 带有可变参数的 kotlin 引用函数并将 Array<out 转换为 List<out

scala - 我如何在 play.api.libs.json.JsValue 和 org.json4s.JValue 之间转换

java - 给定一个 scala 不可变映射,如何在 Java 中插入/删除条目

java - 为什么我不能将 Object 类型的对象添加到 List<?> 中?

c# - C# 中更复杂的扩展泛型

algorithm - 是否有一种有效的算法可以找到哪些 boolean 函数的组合与给定 boolean 函数的输出相匹配?

swift - 如何在 Swift 中执行 for..where 功能?

functional-programming - 寻找 Church 编码(lambda 演算)来定义 < , > , !=