1

Comment puis-je décrire cette grammaire récursive avec des alias de type:Décrire la grammaire récursive avec des alias de type

type FieldValue = Seq[String] :+: String :+: Int :+: Long :+: CNil 
type FieldLeaf = FieldValue :+: SubField :+: CNil 
type SubField = Seq[Field] 
type Field = (String, FieldLeaf) 

En l'état actuel, le compilateur Scala (2.12.1) me donne:

Error:(14, 25) illegal cyclic reference involving type FieldLeaf 
    type Field = (String, FieldLeaf) 

PS le contexte de ceci est l'analyse d'une grammaire récursive avec fastparse.


Modifier (en réponse à @ la réponse de OlivierBlanvillain ci-dessous)

Cette réponse était vraiment une chose de la beauté et exactement ce que je cherchais, je me souviendrai pour l'avenir.

Cependant, pour d'autres raisons, dans ce cas particulier que je devais aller avec ces définitions au lieu:

case class Field(name: String, leaf: FieldLeaf) 
    sealed trait FieldLeaf 
    sealed trait FieldValue extends FieldLeaf 
    case class StringsFieldValue(value: Seq[String]) extends FieldValue 
    case class StringFieldValue(value: String) extends FieldValue 
    case class IntFieldValue(value: Int) extends FieldValue 
    case class LongFieldValue(value: Long) extends FieldValue 
    case class SubField(value: Seq[Field]) extends FieldLeaf 

Voir aussi: Instantiate types from recursive type grammar

+0

Qu'est-ce '' CNil' et: +: '? – Rumid

+0

Aussi, peut-être pourriez-vous expliquer quelle structure il devrait avoir, peut-être que c'est un défaut de conception. Se débarrasser de 'type Subfield' et utiliser' Seq [Field] 'devrait résoudre votre problème, mais peut-être y a-t-il une meilleure solution, par exemple créer des classes supplémentaires. – Rumid

+1

Désolé @Rumid, aurait dû inclure les importations. Je les ai exclus pour la brièveté. C'est sans forme. – eirirlar

Répondre

2

Utilisez un type de point fixe. Par exemple:

case class Fix[F[_]](out: F[Fix[F]]) 

vous permet d'écrire:

type FieldValue = Seq[String] :+: String :+: Int :+: Long :+: CNil 
type FieldLeaf[F] = FieldValue :+: SubField[F] :+: CNil 
type SubField[F] = Seq[F] 
type Field0[F] = (String, FieldLeaf[F]) 

type Field = Fix[Field0]