2010-10-29 167 views
29

我剛剛開始使用Scala,而我認爲應該很容易的東西很難弄清楚。我想實現以下功能:如何在Scala中實現一個通用的數學函數

def square(x:Int):Int = { x * x }

這只是正常的,但如果我想嘗試做任何一種數量的此功能工作,我希望能夠做到以下幾點:

def square[T <: Number](x : T):T = { x * x }

這抱怨說:錯誤:值*是不是類型參數T

我需要實現此一特質中的一員?

+0

對於後人來說,給這個問題一個更具體的標題可能是有用的,比如「我如何在Scala中實現通用數學函數?」。 – 2010-10-30 17:25:59

+0

同意,謝謝。 – jimmyb 2011-05-05 15:49:05

回答

30

這是我在堆棧溢出或關於Scala的first questions之一。問題在於Scala保持與Java的兼容性,這意味着它的基本數字類型等同於Java的基元。

問題在於Java基元不是類,因此沒有允許「數字」超類型的類層次結構。

說得透徹一點,Java和,因此,Scala中,並沒有看到一個Double+和一個Int+之間的共同點。

方式斯卡拉終於繞開這個限制得到的是通過使用Numeric,和它的子類FractionalIntegral,在所謂的類型類模式。基本上,你用這樣的:

def square[T](x: T)(implicit num: Numeric[T]): T = { 
    import num._ 
    x * x 
} 

或者,如果你不需要任何的數字運算,但你打電話做的方法,你可以使用方面的約束語法類型聲明:

def numberAndSquare[T : Numeric](x: T) = x -> square(x) 

欲瞭解更多信息,請參閱我自己的問題的答案。

+1

很好的解釋。我必須爲Typeclass模式谷歌 - 不知道存在。謝謝。 – Collin 2010-10-30 14:35:17

+0

如果你有這個,但是: 'def squareAddOne [T](x:T)(implicit num:Numeric [T]):T = {import num._; x * x + 1}' 如何將Int添加到數字中? – 2016-08-01 15:00:00

+0

哦,我想我的問題是在這裏回答:http://stackoverflow.com/a/2388386/901263 – 2016-08-01 15:03:30

10

您可以定義square爲:

def square[T: Numeric](x: T): T = implicitly[Numeric[T]].times(x,x) 

這種方法的優勢在於,它將爲具有一個隱式轉換爲數字[T](即整型,浮點型,雙,字符任何類型T的工作, BigInt,...或您爲其提供隱式轉換的任何類型)。

編輯: 不幸的是,如果你嘗試像List(1,2,3).map(square)(特別是你遇到麻煩,你會得到一個編譯錯誤,如「無法找到數字類型[T]的證據參數內含價值」爲了避免這個問題,你可以重載square返回一個函數:

object MyMath { 
    def square[T: Numeric](x: T) = implicitly[Numeric[T]].times(x,x) 
    def square[T: Numeric]: T => T = square(_) 
} 

希望有人能夠更好地理解類型inferencer將解釋這是爲什麼

另外,可以撥打如Derek Williams在scala-user mailing list thread中指出的那樣,。

相關問題