首页 > 解决方案 > 斯卡拉.reduce 泛型类型的奇怪行为

问题描述

我一直在想,为什么这段代码不会编译?

Scala中是否有一种方法可以创建通用参数化的方法/函数,并允许像“reduce”这样的操作。

这种行为是否与类型擦除有任何共同点,还是其他?我希望看到对此的广泛解释:)

def func2[B <: Int](data: Seq[B]): Unit = {
    val operation = (a: B, b: B) => a.-(b)

    data.reduce(operation)
  }

编译器说:

type mismatch;
 found   : (B, B) => Int
 required: (Int, Int) => Int

此外,本着同样的精神 - 总体上是否可以使用此方法在参数化集合上调用任何“类似流”的方法:

   def func2[B <: Int](data: Seq[B]): Unit = {
       val operation = (a: B, b: B) => a.-(b)

       data.sum
  }

还给出:

could not find implicit value for parameter num: Numeric[B]

标签: scalasumreduce

解决方案


为什么我不能在集合类型上设置上限,并假设 B 类型(具有该约束)只有我需要的这些方法?

你的假设是正确的。您的上限B使以下编译

val operation = (a: B, b: B) => a.-(b) 

并且也reduce可以在 a 上使用Seq[B],因为Seq它是协变的。

由于编译器知道“ BISA Int”,因此该-方法存在于其上。但是,它仍然会返回一个Int. 因为 的签名+将返回类型限制为Int

def +(x: Int): Int

reduce操作只能理解一种类型。所以如果你有

reduce[B](operation)

它将期望operation是类型(B,B) => B

如果你有

reduce[Int](operation)

它将期望operation是类型(Int,Int) => Int

可以做的一件事是

val operation = (a: Int, b: Int) => a - b

这是安全的,因为您B始终也是Int


推荐阅读