scala中的相互递归类型 [英] mutually recursive types in scala
问题描述
我有一个带有bugtracker问题列表的xml文件。这是原始数据。该模型有不同的问题类型,如任务,子任务,错误,特殊bug。
现在我想解析我的原始数据到任务和子任务的层次结构:
//字段内容的数据类型
抽象类字段
case class Id(raw:string)扩展Field
case class Status(raw:string)extends Field
...
//主模型的数据类型
抽象类问题(id:字符串,...)
案例类任务(id:Id,状态:状态...,子任务:列表[子任务])扩展问题(id,...)
case class Subtask(id:Id,status:Status ...,parent:Task)extends Issue(id,...)
我不知道这种相互递归在理论上是可能的吗?
第二个问题:$ b p>我将模型渲染为一些wiki标记。这适用于重载的递归render():数据类型的类中的字符串。 (可能我应该有一个Renderable超类!?)
什么是最简洁的解析方式,即我想有一个递归
fromXML:scala.xml.Elem =>问题/领域
我会把它放在哪里?它会是什么样子? IIUC,同伴是自动生成的case-classes,所以我不能添加到它?
我有这样的例子:
def fromXml(e:Elem)= e match {
case< a> test< / a> => Id(test)
case _ =>状态(预分析)
}
但是我未能赋予函数a类型。什么是该函数的类型?
我也考虑过将xml-elem直接传递给ADT的构造函数,那会是聪明?还是应该分离XML解析和模型创建?
耶稣在学习了scala基础知识并做了一些脚本之后,函数(并且思考太多的java),我终于明白了如何编写ADT,并且可以像在旧的Haskell时代一样表达自己: - ) 关于不可变,相互依赖的类的初始化,请看 对象>这个问题。
B:关于您的问题 render:Foo => String
函数与可Renderable
超类,这或多或少是一种功能和面向对象方法之间的设计决定。我个人认为他们中的一个比另一个优越,这只是一个品味问题。 针对表达问题的独立可扩展解决方案可以很好地比较这两个,尽管在一个稍微更复杂的上下文中(这是一个伟大的阅读,但是)。
C:编译器,但是如果你还指定了一个伴随对象,编译器会合并这两个对象。
D:对于 Issue
和 Field
而言,这是非常重要的常见超类型,这使得给 fromXML
。不过,你可以使用任一[问题,字段]
,但这对我来说看起来很诡异。一般来说,我会避免将返回完整节点的混合函数(例如 Task
)与返回内部节点的混合函数(例如状态
)。
E:您是否看过现有的解决方案,例如 scalaxb ?您可以在这里找到 和这里。
Is it possible to have mutual recursive types in scala?
I have a xml files with a list of bugtracker issues. It's raw data. The model has different issue-types like "tasks", "subtasks", "bug", "special-bug".
Now I want to parse my raw-data to a hierarchical structure of tasks and subtasks:
// data type for field contents
abstract class Field
case class Id(raw : string) extends Field
case class Status(raw : string) extends Field
...
// data type for primary model
abstract class Issue(id : String, ...)
case class Task(id : Id, status : Status ..., subtasks : List[Subtask] ) extends Issue(id, ...)
case class Subtask(id : Id, status : Status ..., parent: Task) extends Issue(id, ...)
I wonder if this mutual recursion is theoretically possible?
Second question:
I render the model to some wiki-markup. This works fine with an overloaded recursive render() : String in the class for the datatype. (Probably I should have a "Renderable" Superclass !?)
What would be the cleanest way for parsing, i.e. I'd like to have a recursive
fromXML : scala.xml.Elem => Issue / Field
Where would I put it? How would it look like? IIUC, the companion is autogenerated for case-classes so I cant add to it?
I have this e.g.:
def fromXml(e : Elem) = e match {
case <a>test</a> => Id("test")
case _ => Status("Pre-analysed")
}
But I failed to give the function a type. What is the type of that function ?
I also thought about passing the xml-elem directly to the constructor of the ADT, would that be clever? Or should I separate XML-parsing and model-creation ?
Jesus, after learning the scala basics and doing some scripts and functions (and thinking too much java), I finally understood how to write ADTs and can express myself nearly as in good old Haskell times :-)
A: Regarding the initialisation of immutable, mutually dependent classes, have a look at this question.
B: Regarding your question render: Foo => String
function vs. Renderable
superclass, this is IMHO more or less a design decision between a functional and an object-oriented approach. I personally don't think that one of them is superior to the other, it is just a matter of taste. The paper "Independently Extensible Solutions to the Expression Problem" has a nice comparison between the two, although in a slightly more elaborate context (it is a great read, however).
C: Companion objects are created by the compiler, but if you also specify a companion object, the compiler will merge the two.
D: In your current class hierarchy there is no non-trivial common supertype for Issue
and Field
, which makes it difficult to give a meaningful return type for fromXML
. You could work with an Either[Issue, Field]
, though, but this looks fishy to me. In general, I would avoid mixing functions that are supposed to return full-fledged nodes (e.g., Task
) with those that return "internal" nodes (e.g., Status
).
E: Did you had a look at existing solutions, e.g. scalaxb? You can find more links here and here.
这篇关于scala中的相互递归类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!