2010-04-18 72 views
3

我想创建一个方法总和,我可以调用不同的类型,特别是sum(1,2)。如何定义引用自身的结构类型?

类型可加成= {DEF +(一个:可添加

def sum[A](a1: A, a2: A) = a1 + a2 

这是因为编译器不能告诉如果A有一个方法 '+'

我试图定义的结构类型出现故障)}

失败的原因的非法循环参考

我怎样才能无需延长特定性状的一种安全的方式实现这一目标?

+1

相关:http://stackoverflow.com/questions/485896/how-does-one-write-the-pythagoras-theorem-in-scala – missingfaktor 2010-04-18 04:43:22

+0

也看到这篇博客文章由瑞奇克拉克森:http:// rickyclarkson。 blogspot.com/2009/01/typeclass-pattern.html – missingfaktor 2010-04-18 04:54:18

回答

7

Scala不支持不带附加编译器参数的递归类型别名(特别是,-Yrecursion)。这部分是为了保持类型检查器在可判定性方面至少有(尽管,正如我们发现的那样,即使没有递归类型别名,类型系统也是图灵完备,所以它并不重要)。

做这种事情的正确方法是用类型类。 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 

值得注意的是斯卡拉2.8有一个类似于Numeric类型的东西。