2010-10-27 8 views
4

J'ai créé une classe qui peut être paramétrés par tout ce qui peut être converti en numériqueScala - conversion implicite de l'INT numérique [Int]

class Complex[T <% Numeric[T]] (val real : T, val imag : T) { 
    //... complex number methods ... 
} 

Ensuite ailleurs dans le code je tente:

var myComplex = new Complex(0, 1) 

Cela soulève une erreur de compilation car (de manière surprenante) il n'y a pas de conversion implicite entre Int et Numeric [Int] ou même entre Int et Integral [Int].

Ai-je raté quelque chose? Y a-t-il une conversion implicite quelque part que je ne vois pas?

Il existe un objet implicite appelé IntIsIntegral défini dans Numeric.scala. Je l'ai essayé d'utiliser cette option pour créer ma propre méthode de conversion implicite:

def implicit intToNumericInt(val i : Int)(implicit n : IntIsIntegral) = n.fromInt(i) 

Je suis surpris que cela est nécessaire et, de toute façon, il semble conduire à une récursion infinie dans la méthode .fromInt.

Je suis sûr qu'il me manque quelque chose de basique (comme vous pouvez le dire, je suis nouveau à Scala) donc j'apprécierais un point dans la bonne direction.

Comme vous pouvez le voir dans l'exemple, j'essaie de faire fonctionner une implémentation de nombres complexes qui peut accepter et travailler avec n'importe quel type numérique. J'espère contribuer au projet scalala (algèbre linéaire). Suite à cela, je veux introduire un trait qui décrit les responsabilités des éléments dans une matrice (principalement juste les opérateurs + et *) et le rattrapage de support pour les nombres complexes dans la bibliothèque de manipulation de la matrice.

Répondre

9

Vous utilisez ce mot de passe. L'utilisation correcte est comme ceci:

class Complex[T](val real : T, val imag : T)(implicit num: Numeric[T]) { 
    import num._ // make implicit conversions available 
    //... complex number methods ... 
} 

Il est la même différence entre Ordered et Ordering. Une instance Ordered[T] peut être comparée à T, tandis qu'une Ordering[T] fournit une méthode qui compare un couple de T.

+0

D'après ce que je comprends, le: T <% numérique [T] est le sucre syntaxique pour ajouter le (implicite num: [T] Numérique) mais je suppose que l'utilisation du sucre signifie que je n'ai pas la variable disponible pour faire: importer num._ // rendre les conversions implicites disponibles J'ai effectivement essayé le (implicit num: Numeric [T]) out mais cela n'a pas fonctionné pour moi. Je rapporterai demain si l'importation num._ aide! Merci. –

+2

@David: 'T <% Numeric [T]' est un sucre syntaxique pour ajouter '(implicite ev: T => Numérique [T])', et 'T: Numérique [T]' est un sucre syntaxique pour ajouter ' (ev implicite: Numérique [T]) '. Le premier s'appelle view bound, et le second s'appelle typeclass bound. – missingfaktor

+2

@missingfaktor Le second est appelé un contexte lié, et arrive à être utilisé pour le modèle de classe de type. –

2

En Scala 2.8, il peut aussi être écrit comme

class Complex[T: Numeric] (val real : T, val imag : T) { 

    def +(that: Complex[T]) = { 
    val r = implicitly[Numeric[T]].plus(this.real, that.real) 
    val i = implicitly[Numeric[T]].plus(this.imag, that.imag) 
    new Complex(r, i) 
    } 

} 

Cette syntaxe est certes un peu dense, mais il peut être rendu plus lisible comme ceci:

class Complex[T: Numeric] (val real : T, val imag : T) { 
    val num = implicitly[Numeric[T]] 

    def +(that: Complex[T]) = { 
    new Complex(num.plus(this.real, that.real), num.plus(this.imag, that.imag)) 
    } 

} 

La déclaration class C[T: M](...) { val x = implicitly[M[T]] serait semble être équivalent à class C[T](...)(implicit x: M[T]) { import x._ comme indiqué dans les commentaires à la solution précédente. Ce n'est pas simplement du sucre syntaxique, car il y a des différences dans la façon dont il est compilé, par ex. dans le premier cas x est une méthode, et dans le second cas c'est un champ.

+0

A ce stade, je pense qu'il est plus clair d'avoir le num (implicite num: Numeric [T]) en utilisant ensuite import num._ plutôt que d'utiliser l'opération implicite qui ressemble un peu comme par magie :) Si je ne voulais pas importer des méthodes de Numeric alors la syntaxe que vous suggérez serait certainement plus propre. –

+0

J'ai mis à jour la réponse pour prendre en compte votre commentaire. –