1

我如何描述與類型別名這個遞歸語法:描述與類型別名遞歸語法

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

既然這樣,Scala編譯器(2.12.1)給我:

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

PS上下文是用fastparse解析遞歸語法。


編輯(在響應低於@ OlivierBlanvillain的答案)

這個答案真的是美的東西,正是我一直在尋找,我會記住它的未來。

然而,由於其他原因,在這種特殊情況下,我不得不去與這些定義來代替:

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 

參見: Instantiate types from recursive type grammar

+0

什麼是'CNil'和':+:'? – Rumid

+0

另外,也許你可以解釋它應該有什麼結構,也許這是設計錯誤。 擺脫'類型子字段'和使用'Seq [Field]'應該可以解決你的問題,但也許有更好的解決方案,例如創建額外的類。 – Rumid

+1

對不起@Rumid,應該包括進口。爲了簡潔,我排除了它們。它是無形的。 – eirirlar

回答

2

使用一個固定點類型。例如:

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

讓你寫:

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]