2010-04-21 4 views
4

J'ai un problème avec les génériques scala. Alors que la première fonction je définissais ici semble être tout à fait correct, le compilateur se plaint de la deuxième définition avec:Scala: "Le type de paramètre dans l'affinement structurel ne peut pas faire référence à un type abstrait défini en dehors de ce raffinement"

error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement 
    def >>[B](a: C[B])(implicit m: Monad[C]): C[B] = { 
     ^

ce que je fais mal ici? IMPORTANT: Ce n'est pas une question sur les monades, c'est une question de polymorphisme scala en général.

EDIT: Voici ma définition Monad

trait Monad[C[_]] { 
    def >>=[A, B](a: C[A], f: A => C[B]): C[B] 
    def >>=[B](a: C[B]): C[B] 
    def apply[A](a: A): C[A] 
} 

BTW: J'utilise scala 2.8RC1

Cordialement, raichoo

+0

Il serait utile si vous aviez votre définition de 'Monad' ici. La partie 'Monad [C]' semble suspecte (j'aurais pensé que Monad [C [_]] 'serait utilisée), mais c'est difficile à dire sans savoir ce qu'est' Monad'. –

+0

Le problème se résume à ce que 'new {...}' produit une instance d'un type structurel anonyme. Scala a quelques limitations sur la façon dont les paramètres de type de l'extérieur peuvent être utilisés dans les types structurels, pour faciliter les invocations de méthodes réfléchissantes. Ces limitations sont quelque peu plus strictes que nécessaire (pour pécher par sécurité). Vous pouvez contourner le problème en remplaçant simplement le type structurel anonyme par un type local nommé, comme indiqué dans la réponse. –

Répondre

10

Remplir les blancs dans votre exemple, je fait ce compiler:

trait Monad[C[_]] { 
    def >>=[A, B](f: A => C[B]): C[B] 
    def >>[B](a: C[B]): C[B] 
} 

trait Lifter[C[_]] { 
    class D { 
    def >>=[A, B](f: A => C[B])(implicit m: Monad[C]): C[B] = { 
     m >>= f 
    } 
    def >>[B](a: C[B])(implicit m: Monad[C]): C[B] = { 
     m >> a 
    } 
    } 

    implicit def liftToMonad[A](c: C[A]) = new D 
} 
0

Merci, cela a vraiment aidé. Votre réponse m'a orienté dans la bonne direction. J'ai écrit la chose à ceci:

trait Lifter[C[_]] { 
    class Wrapper[A](c: C[A]) { 
    def >>=[B](f: A => C[B])(implicit m: Monad[C]): C[B] = { 
     m >>= (c, f) 
    } 
    def >>[B](b: C[B])(implicit m: Monad[C]): C[B] = { 
     m >> (c, b) 
    } 
    } 

    implicit def liftToMonad[A](c: C[A]): Wrapper[A] = new Wrapper(c) 
} 

Merci beaucoup.

Cordialement, raichoo

Questions connexes