2010-02-16 8 views
4

Comment définir cette classe dans scalaDéfinir autoréférencement classe Scala (classe récursive)

data NestedList a = Elem a | List [NestedList a]

Cela signifie Haskell un NestedList est un type qui peut contenir Elem ou d'une autre NestedList. Est-il possible de faire ce genre de définitions récursives en scala?

En fait, ce que je suis en train de acheive

Vérifiez Problem 7 dans cette page.

Mise à jour ....
follwing les réponses ci-dessous, j'ai créé les NestedList classes et cas pour Trait Elem et NList. Essayer de mettre en œuvre le flatten, je suis coincé ici ..

def flatten[T](xs: NestedList[T]): List[T] = xs match{ 
    case Elem(xs) => List(xs) 
    //case NList //have to fill this case 
} 

Répondre

5

Algebraic Types de données de Haskell sont traduits dans idiomatiquement hiérarchies de classes scellées à Scala.

Par exemple:

sealed abstract class List[+A] 

case class Nil extends List[Nothing] 

case class Elem[T](head: T, tail: List[T]) extends List[T] 

MISE À JOUR

réponse Thomas montre la définition de type récursif bien. Cependant, il est intéressant que vous ne pouvez pas faire NList une classe de cas - une erreur de type est signalée pour la méthode synthétisée sameElements, qui est utilisée dans equals. Cela semble similaire à: https://lampsvn.epfl.ch/trac/scala/ticket/2867

Il fonctionne est les paramètres répétés sont remplacés par Seq:

sealed trait NestedList[A] 
case class Elem[A](e : A) extends NestedList[A] 
case class NList[A](val e : Seq[NestedList[A]]) extends NestedList[A] 
+2

Ne sont pas ces types de données algébriques? –

+0

modifié, merci! – retronym

+0

Je ne suis pas sûr, je l'ai suivi, Pouvez-vous s'il vous plaît me montrer un exemple de la façon de définir la même classe que j'ai définie dans la question. –

4

Cela devrait fonctionner.

sealed trait NestedList[A] 
case class Elem[A](val e : A) extends NestedList[A] 
case class NList[A](val e : Seq[NestedList[A]]) extends NestedList[A] 

def flatten[T](xs: NestedList[T]): Seq[T] = xs match{ 
    case Elem(x) => List(x) 
    case NList(xs) => xs flatMap (flatten(_)) 
} 
+2

Veuillez utiliser des classes de cas. – Dario

1
sealed abstract class NestedList[A] { 
    def flatten: NList[A] 
} 

case class Elem[A](e: A) extends NestedList[A] { 
    override def flatten = NList(Elem(e)) 
} 

case class NList[A](es: NestedList[A]*) extends NestedList[A] { 
    override def flatten = NList(es flatMap (_.flatten.es): _*) 
} 
+0

Cela produit un message d'erreur avec 2.8 Beta 1: : 5: error: type arguments [NestedList [A]] ne sont pas conformes à la méthode même Limites des paramètres de type Elements [B>: NestedList [Any]] classe NList [A] (es: NestedList [A] *) étend NestedList [A] –

+0

@Thomas cela fonctionne sur ma plus récente Scala 2.8. –

+0

@Thomas d'ailleurs, si vous l'utilisez sur REPL, n'oubliez pas de placer tout cela à l'intérieur d'un objet, de sorte qu'ils sont considérés comme définis dans le même module. –

3

Voir 99 problems in Scala pour les versions Scala des problèmes.

La solution liée à partir de ce site est:

def flatten(ls: List[Any]): List[Any] = ls flatMap { 
    case ms: List[_] => flatten(ms) 
    case e => List(e) 
} 
+0

A + 1 pour le lien, –

Questions connexes