2010-12-14 73 views
2

一個觀點我已經試過這行代碼Scala編譯器不能識別綁定

def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2}) 

但是在編譯時,當我看到在源的數字特徵我得到這個錯誤

error: value * is not a member of type parameter A 
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2}) 

,我看到一個定義爲*的操作。

我在做什麼錯?

回答

6

Numeric的實例本身不是數字,但它是提供操作來執行算術的對象。例如,Numeric[Int]類型的對象num可以添加兩個整數像這樣:num.plus(3, 5)該操作的結果是整7.

對於整數,這是非常簡單。但是,對於所有基本數字類型,都有一個隱式Numeric的實例可用。如果你定義你自己的數字類型,你可以提供一個。

因此,您應該打開A的範圍,並添加一個類型爲Numeric[A]的隱式參數,並使用該參數進行計算。就像這樣:

def **[A](l:List[A],m:List[A])(implicit num:Numeric[A])=l.zip(m).map({t=>num.times(t._1, t._2)}) 

當然,num.times(a,b)看起來比a*b那麼優雅。在大多數情況下,人們可以忍受這一點。但是,您可以在Ops類型的對象,它支持運營商包的價值a,就像這樣:

// given are: num:Numeric[A], a:A and b:A 
val a_ops = num.mkNumericOps(a) 
val product = a_ops * b 

由於該方法mkNumericOps聲明implicit,你也可以導入並含蓄地使用它:

// given are: num:Numeric[A], a:A and b:A 
import num._ 
val product = a * b 
+1

我會在哪裏把進口num._聲明我的**功能的情況下? – user44242 2010-12-14 09:00:08

+1

您需要在等號後面打開一個塊。我沒有測試這個,但我想它應該看起來像這樣:'def ** [A](l:List [A],m:List [A])(implicit num:Numeric [A])= {import num._; l.zip(m).map({t => t._1 * t._2})}' - 儘管如此,我會努力去嘗試。我不確定隱式包裝Ops對象的創建是否會影響性能,或者是否會被編譯器優化。 – Madoc 2010-12-14 09:04:56

+0

我希望如果啓用逃生分析,它應該進行優化,但沒有保證。 – 2010-12-14 18:39:37

2

你也可以用context bound來解決這個問題。從this answer使用context方法,你可以寫:

def **[A : Numeric](l:List[A],m:List[A]) = 
    l zip m map { t => context[A]().times(t._1, t._2) } 

def **[A : Numeric](l:List[A],m:List[A]) = { 
    val num = context[A]() 
    import num._ 
    l zip m map { t => t._1 * t._2 } 
} 
相關問題