【问题标题】:Define self referencing Scala class (recursive class)定义自引用Scala类(递归类)
【发布时间】:2011-01-17 10:34:01
【问题描述】:

如何在scala中定义这个类

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

这在 Haskell 中意味着 NestedList 是一个可以包含 Elem 或另一个 NestedList 的类型。是否可以在 scala 中进行这种递归定义?

其实这就是我想要实现的目标

在此页面中查看Problem 7

已更新....
按照下面的答案,我为ElemNList 创建了NestedList Trait 和case 类。 试图实现flatten,我被困在这里..

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

【问题讨论】:

    标签: scala haskell functional-programming


    【解决方案1】:

    来自 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]
    

    更新

    Thomas 的回答很好地展示了递归类型定义。但是,有趣的是,您不能将NList 设置为案例类——在equals 中使用的合成方法sameElements 会报告类型错误。这听起来类似于: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]
    

    【讨论】:

    • 这些不是代数数据类型吗?
    • 我不确定,我跟着它,你能告诉我如何定义我在问题中定义的同一个类的例子。
    • @retronym 感谢您的更新。但我仍然无法获得问题的解决方案(请参阅有问题的问题链接)。简而言之,我正在尝试实现与这个 haskell 函数等效的东西... data NestedList a = Elem a | List [NestedList a] flatten :: NestedList a -> [a] flatten (Elem x) = [x] flatten (List x) = concatMap flatten x
    • @retronym 请检查更新。这是代码 sn-p.. snipt.org/vmkl
    • @Daniel:我使用的是 2.8 beta1。 #2867 已在 5 周前修复...不确定是否处于测试阶段。
    【解决方案2】:

    这应该可行。

    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(_)) 
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:
        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): _*)
        }
        

        【讨论】:

        • 这会产生一条带有 2.8 Beta 1 的错误消息::5: error: type arguments [NestedList[A]] do not conform to the method same Elements's type parameter bounds [B >: NestedList[ Any]] case class NList[A](es: NestedList[A]*) extends NestedList[A]
        • @Thomas 顺便说一下,如果你在 REPL 上运行它,记得把它全部放在一个对象中,这样它们就被认为是在同一个模块中定义的。
        猜你喜欢
        • 1970-01-01
        • 2021-06-22
        • 1970-01-01
        • 2017-02-13
        • 1970-01-01
        • 2020-01-09
        • 1970-01-01
        • 1970-01-01
        • 2021-10-14
        相关资源
        最近更新 更多