2010-02-10 17 views
6

Ho il seguente problema: Ho una funzione che accetta un parametro [Double] come parametro, esegue alcune operazioni aritmetiche sugli elementi della lista e restituisce il risultato . Vorrei che la funzione accettasse anche List [Int]. Ecco un esempio:scala per definire le funzioni accettando un elenco di diversi tipi numerici

def f(l: List[Double]) = { 
    var s = 0.0 
    for (i <- l) 
     s += i 
    s 
} 

val l1 = List(1.0, 2.0, 3.0) 
val l2 = List(1, 2, 3) 

println(f(l1)) 
println(f(l2)) 

Naturalmente la seconda println non riesce dal momento che f richiede Lista [Doppia] e non lista [Int].

Si noti inoltre la formulazione non scala dello stile della somma all'interno della funzione f per dimostrare la necessità di utilizzare 0 (o altre costanti) all'interno della funzione stessa (se sommi i valori Int devo iniziare a 0 non 0.0.

Qual è il modo migliore (meno codice) per ottenere il lavoro di funzione su entrambi doppio e Int?

(ho visto qualcosa di circa 2,8 tratto numerica di io non sono così sicuro come usarlo ...)

Grazie a tutti per l'aiuto

risposta

7

Con scala 2.8 e utilizzando numerico si combinano per conversione implicita tuo esempio potrebbe essere scritto come:

import Numeric._ 
def f[T](l: List[T])(implicit n: Numeric[T]):T = { 
    var s = n.zero 
    for (i <- l) 
     s = n.plus(s, i) 
    s 
} 

val l1 = List(1.0, 2.0, 3.0) 
val l2 = List(1, 2, 3) 

println(f(l1)) 
println(f(l2)) 

//or 
def f2[T](l: List[T])(implicit n: Numeric[T]):T = { 
import n._ 
var s = zero 
for (i <- l) 
    s += i 
s 
} 
println(f2(l1)) 
println(f2(l2)) 

Ora un altro esempio facendo la somma in un modo tutto scala:

def sum[T](l:List[T])(implicit n: Numeric[T]):T = { 
import n._ 
l.foldLeft(zero)(_ + _) 
} 

println(sum(l1)) 
println(sum(l2)) 

//or since 2.8 Seq include already a sum function 
def sum[T](l:List[T])(implicit n: Numeric[T]):T = l.sum 

println(sum(l1)) 
println(sum(l2)) 
+2

'def riassumere [T: Numeric] (l: Lista [T]) = l.sum' farà. –

+0

@Thomas, sì, certo;) – Patrick

4

This answer utilizza il tratto numerico.

import Numeric._ 
def f[A](l: List[A])(implicit numeric: Numeric[A]) = 
    l reduceLeft ((l,r) => numeric.plus(l, r)) 

o utilizzando limiti di contesto:

def f[A : Numeric](l: List[A]) = 
    l.reduceLeft((l,r) => implicitly[Numeric[A]].plus(l, r))