2010-04-18 73 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類型的東西。