2017-09-29 53 views
0

這可能之前已經問過,我發現了一些舊的答案,但我覺得很難接受它們。斯卡拉等值的哈斯克爾號

我試圖寫一個函數,對數和一起把它們添加:

object Add { 
    def[A](a1: A, a2: A) = a1 + a2 
} 

,我得到的錯誤:

[error] found : A 
[error] required: String 

現在很明顯斯卡拉可是沒有辛德米爾納類型推斷但你會期望有一些抽象類,比如Number,包含所有的基本操作。如果有我無法找到它。 相反,我發現我應該使用類型類:

def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = { 
    a1 + a2 
} 

不工作...但是:

def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = { 
    import n._ 
    a1 + a2 
} 

呢,現在這似乎並不特別乾淨給我。請告訴我有更好的辦法!

甚至沒有常規的類使用像;

def add[A: Numeric](a1: A, a2: A) = { 
    a1 + a2 
} 

的作品,而不是我要補充2行:

def add[A: Numeric](a1: A, a2: A) = { 
    val n = implicitly[Numeric[A]] 
    import n._ 
    a1 + a2 
} 

我感覺就像我失去了一些東西在這裏根本原因不應該這麼難兩數相加

更新:

感謝我的答案,我發現有可能做到以下幾點:

import scala.math.Numeric._ 
import scala.math.Numeric.Implicits._ 

def add[A: Numeric](a1: A, a2: A) = { 
    a1 + a2 
} 

這真的是我一直想要做的。

回答

5

當您需要證據證明A是數字時,該證據知道如何處理類型爲A的元素。

def add[A](a1: A, a2: A)(implicit ev: Numeric[A]) = { 
    ev.plus(a1,a2) 
} 

使用更復雜的中綴表示法需要額外的暗示。

def add[A](a1: A, a2: A)(implicit ev: Numeric[A]) = { 
    import Numeric.Implicits._ 
    a1 + a2 
} 

Not even regular type class use ...

應當注意的是,你所謂的「普通型類使用」

def add[A: Numeric](a1: A, a2: A) = {... 

...實際上是由編譯器改寫成這樣的事情...

def add[A](a1: A, a2: A)(implicit evidence$1 Numeric[A]) = {... 

...除了編譯器不是約束ned到任何特定的名稱mangling公式,因此您不能依賴具有可預測名稱的隱式參數。因此implicitly用於重新實現隱式參數。

+0

謝謝,我想我的問題是我錯過了Numerics伴侶上的Implicits對象,並認爲我需要從函數內的證據導入隱式操作,這感覺很奇怪,因爲我想在遞歸函數中使用它 – user25470

1

您也可以使用數字型類方法加上直接

def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = { 
    n.plus(a1,a2) 
} 

def add[A: Numeric](a1: A, a2: A) = { 
    implicitly[Numeric[A]].plus(a1,a2) 
} 

爲了使用管道符,你需要一個隱含的範圍,以A型轉換以適當的方法來上課。這就是爲什麼我們需要導入type-class提供的implicts。