2010-12-14 5 views
2

J'ai essayé cette ligne de codecompilateur Scala ne reconnaît pas une vue liée

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

Cependant sur la compilation, je reçois cette erreur

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}) 

Quand je regarde la source pour le caractère numérique , Je vois une op * définie.

Qu'est-ce que je fais mal?

Répondre

6

L'instance de Numeric n'est pas un nombre en soi, mais un objet qui propose des opérations pour effectuer l'opération arithmétique. Par exemple, un objet num de type Numeric[Int] peut ajouter deux entiers comme ceci: num.plus(3, 5) Le résultat de cette opération est l'entier 7.

Pour les entiers, ce qui est très trivial. Cependant, pour tous les types numériques de base, il existe une instance implicite disponible de Numeric. Et si vous définissez vos propres types numériques, vous pouvez en fournir un.

Par conséquent, vous devez laisser les limites pour A ouvert et ajouter un paramètre implicite de type Numeric[A], avec lequel vous effectuez les calculs. Comme ceci:

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

Bien sûr, num.times(a,b) semble moins élégante que a*b. Dans la plupart des cas, on peut vivre avec ça. Cependant, vous pouvez envelopper la valeur a dans un objet de type Ops qui prend en charge les opérateurs, comme ceci:

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

Puisque la méthode mkNumericOps est déclarée implicit, vous pouvez également importer et utiliser implicitement:

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

Où je mettrais la déclaration de num._ à l'importation dans le cadre de ma fonction **? – user44242

+1

Vous devez ouvrir un bloc après le signe égal. Je n'ai pas testé cela, mais je suppose qu'il devrait ressembler à ceci: 'def ** [A] (l: liste [A], m: liste [A]) (num implicite: Numeric [A]) = {import num._; l.zip (m) .map ({t => t._1 * t._2})} '- J'essaierais de m'en passer cependant; Je ne suis pas sûr si la création de l'objet Ops de wrapper implicite affecte les performances ou si elle sera optimisée par le compilateur. – Madoc

+0

Je pense qu'il devrait être optimisé si l'analyse d'échappement est activée, mais aucune garantie. –

2

Vous pouvez également résoudre ce problème avec un context bound. En utilisant la méthode context de this answer, vous pouvez écrire:

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

ou

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