2011-11-17 5 views
6

Come si può creare una classe che comporti confronti matematici con e su qualsiasi tipo numerico in Scala?Confronti con i tipi numerici di Scala?

Un approccio ovvio:

import math.Numeric.Implicits._ 

class Ops[T : Numeric] { 
    def add(a: T, b: T) = a + b 
    def gt(a: T, b: T) = a > b 
} 

mi fa guadagnare questo ...

Ops.scala:7: value > is not a member of type parameter T 

Hmmm ... si può fare la matematica con i tipi numerici, ma non possiamo confrontarli?

Quindi diciamo anche che è TOrdered[T] ...

class Ops[T <: Ordered[T] : Numeric] { 
    def add(a: T, b: T) = a + b 
    def gt(a: T, b: T) = a > b 
} 

che compila. Ma prova ad usarlo?

new Ops[Int].gt(1, 2) 

E ho ...

Ops.scala:13: type arguments [Int] do not conform to class Ops's type parameter bounds [T <: Ordered[T]] 

Così come posso operare su un certo tipo che è sia ordinato e numerica?

risposta

14
scala> import Ordering.Implicits._ 
import Ordering.Implicits._ 

scala> import Numeric.Implicits._ 
import Numeric.Implicits._ 

scala> class Ops[T : Numeric] { 
    | def add(a: T, b: T) = a + b 
    | def gt(a: T, b: T) = a > b 
    | } 
defined class Ops 

scala> new Ops[Int].gt(12, 34) 
res302: Boolean = false 
+0

Nice, non era a conoscenza di questo tipo di importazione globale in contrasto con l'importazione locale 'numeric.mkXXXOps'. Lo userà. –

+2

'Numerico' estende' Ordine', quindi chiedere un contesto di 'Ordine' è ridondante! 'T: Numeric' è sufficiente. –

+0

@Sciss: hai ragione. Modificato, grazie. – missingfaktor

4

è necessario importare mkNumericOps e/o mkOrderingOps:

val num = implicitly[Numeric[T]] 

o

class Ops[T](implicit num: Numeric[T]) 

poi:

import num.{mkNumericOps,mkOrderingOps} 

Ora è possibile confrontare e calc con loro. Forse ti saluta per la prima parte della tua domanda.

A proposito: ordinato e numerico funziona così:

class Ops[T: Ordered: Numeric] 
+0

Sì, funziona! Grazie! Dove è stato documentato? – Tim

+2

Questo sarebbe 'T: Ordinamento: numerico' (o' T <: Ordinato: numerico' o 'T <% ordinato: numerico') –

+0

@Tim Ho avuto il tuo problema da solo e ho pensato che ci deve essere un modo non goffo chiamare 'gt'. Quindi ho dato un'occhiata all'API e c'era questo misterioso 'mkOrderingOps' ... Dai sempre un'occhiata all'API! –