我想创建一个方法求和,我可以调用不同的类型,特别是sum(1,2)。
def sum[A](a1: A, a2: A) = a1 + a2
这会失败,因为编译器无法判断A是否有方法'+'
我尝试定义结构类型:
输入Addable = {def +(a:Addable)}
由于非法循环引用而失败
如何在不需要A扩展特定特征的情况下以类型安全的方式实现此目的?
答案 0 :(得分:7)
Scala不支持没有其他编译器参数的递归类型别名(具体来说,-Yrecursion
)。这部分是为了使类型检查器在可判定性范围内保持至少有点(但是,正如我们已经发现的那样,即使没有递归类型别名,类型系统也是Turing Complete,所以它并不重要)。
执行此类操作的正确方法是使用类型类。 Scala将这些编码为隐式视图边界。例如:
trait Addable[A] {
def zero: A
def add(x: A, y: A): A
}
implicit object IntAddable extends Addable[Int] {
def zero = 0
def add(x: Int, y: Int) = x + y
}
implicit object DoubleAddable extends Addable[Double] {
def zero = 0
def add(x: Double, y: Double) = x + y
}
// ...
def sum[A](x: A, y: A)(implicit tc: Addable[A]) = tc.add(x, y)
当然,这也允许你做一些奇特的事情,例如以类型安全的方式对Seq
的内容进行求和:
implicit def summableSeqSyntax[A](seq: Seq[A])(implicit tc: Addable[A]) = new {
def sum = seq.foldLeft(tc.zero)(tc.add)
}
List(1, 2, 3, 4).sum // => 10
List(true, false).sum // does not compile
值得注意的是,Scala 2.8与Numeric
类型类非常接近。