定义自引用Scala类(递归类)

时间:2010-02-16 14:55:11

标签: scala haskell functional-programming

如何在scala中定义此类

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

这在Haskell中意味着NestedList是一个Type,它可以包含Elem或另一个NestedList。是否可以在scala中执行这些递归定义?

实际上这就是我想要实现的目标

点击此页面中的Problem 7

更新....
在下面的答案中,我为NestedListElem创建了NList特征和案例类。 试图实现flatten,我被困在这里..

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

4 个答案:

答案 0 :(得分:5)

来自Haskell的代数数据类型在Scala中被惯用地转换为密封的类层次结构。

例如:

sealed abstract class List[+A]

case class Nil extends List[Nothing]

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

<强>更新

托马斯的回答很好地展示了递归类型定义。但是,有趣的是,您无法使NList成为案例类 - 报告了sameElements中使用的合成方法equals的类型错误。这听起来类似于:https://lampsvn.epfl.ch/trac/scala/ticket/2867

可行的是重复的参数被替换为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]

答案 1 :(得分:4)

这应该有用。

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 :(得分:3)

有关问题的Scala版本,请参阅99 problems in Scala

该网站的链接解决方案是:

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

答案 3 :(得分: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): _*)
}