Question

Je suis en train de définir un type de structure définissant une collection qui a une méthode « add » (par exemple, une collection java). Avec cela, je veux définir quelques fonctions de commande de plus qui fonctionnent sur une certaine collection

object GenericTypes {
  type GenericCollection[T] = { def add(value: T): java.lang.Boolean}
}

import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection[X]] {
    def map[V](fn: (T) => V): CollectionType[V]
    ....
}

class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]

Cela ne compile pas avec l'erreur suivante

error: Parameter type in structural refinement may not refer to abstract type defined outside that same refinement 

J'ai essayé de supprimer le paramètre sur GenericCollection et de le mettre sur la méthode:

object GenericTypes {
  type GenericCollection = { def add[T](value: T): java.lang.Boolean}
}
import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection]

class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]

mais je reçois une autre erreur:

error: type arguments [T,java.util.List] do not conform to trait HigherOrderFunctions's type parameter bounds [T,CollectionType[X] <: org.scala_tools.javautils.j2s.GenericTypes.GenericCollection]

Quelqu'un peut-il me donner quelques conseils sur la façon d'utiliser le typage structurel avec des paramètres abstraits typés à Scala? Ou comment réaliser ce que je cherche à accomplir? Merci beaucoup!

Était-ce utile?

La solution

Comme vous pouvez le voir dans billet 1906 ne pouvez pas utiliser type abstrait défini en dehors du type de construction en raison du manque d'informations de type à l'exécution.

Ceci est indiqué dans le Scala Langue référence (3.2.7 Types composés) :

Within a method declaration in a structural refinement, the type of
any value parameter may only refer to type parameters or abstract types that are
contained inside the refinement.

La façon habituelle d'ajouter de nouvelles méthodes à un type est par conversion de type implicite.

trait HigherOrderFunctions[T, CC[_]] {
    def zap[V](fn: () => V): CC[V]
}

class RichJList[T](list: java.util.List[T]) extends HigherOrderFunctions[T, java.util.List]{
    def zap[V](fn: () => V): java.util.List[V] = {
        val l = new java.util.ArrayList[V]
        l add fn()
        l
    }
}
implicit def list2RichList[T](l : java.util.List[T]) = new RichJList(l)
new java.util.ArrayList[AnyRef]() zap (() => 2)

Si le compilateur voit que le type manqué la méthode zap il convertira à un type qui a la méthode zap avec une méthode de conversion implicite (ici list2RichList) portée.

scala> new java.util.ArrayList[AnyRef]() zap (() => 2)
res0: java.util.List[Int] = [2]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top