【问题标题】:Describe recursive grammar with type aliases用类型别名描述递归语法
【发布时间】:2017-03-02 06:36:22
【问题描述】:

我如何用类型别名来描述这种递归语法:

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

【问题讨论】:

  • 什么是CNil:+:
  • 另外,也许你可以解释一下它应该有什么结构,也许是设计错误。摆脱 type Subfield 并使用 Seq[Field] 应该可以解决您的问题,但也许有更好的解决方案,例如创建额外的类。
  • 对不起@Rumid,应该包括进口。为简洁起见,我将它们排除在外。它是无形的。

标签: scala recursive-datastructures recursive-descent type-alias fastparse


【解决方案1】:

使用固定点类型。例如:

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]

【讨论】:

    猜你喜欢
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    相关资源
    最近更新 更多