Scala 用Trait实例化Case类

Scala 用Trait实例化Case类,scala,case-class,traits,Scala,Case Class,Traits,如何根据下面的trait和case类实例化树 sealed trait Tree[+A] case class Leaf[A](value: A) extends Tree[A] case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A] 资料来源: 示例:如何对以下类型为String的树进行编码 "top" / \ "middle-left" "middl

如何根据下面的trait和case类实例化树

sealed trait Tree[+A] 
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
资料来源:

示例:如何对以下类型为
String
的树进行编码

           "top"
          /     \
  "middle-left"    "middle-right"
       /          \
  "bottom-left"   "bottom-right"

使用您给定的类层次结构,您将无法创建与所需的示例树完全相似的内容,因为分支只能接受左、右子树,而不能接受值(文本“top”)

如果您希望分支节点也有一个值,我将修改您的类层次结构,如下所示:

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](value: A, left: Option[Tree[A]] = None, right: Option[Tree[A]] = None) extends Tree[A]
val tree = Branch("top",
                  Some(Branch("middle-left", Some(Leaf("bottom-left")))),
                  Some(Branch("middle-right", right = Some(Leaf("bottom-right")))))
请注意子树的选项al性质,默认值为None,允许在不使用null的情况下丢失左或右子树

然后可以按如下方式生成示例树:

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](value: A, left: Option[Tree[A]] = None, right: Option[Tree[A]] = None) extends Tree[A]
val tree = Branch("top",
                  Some(Branch("middle-left", Some(Leaf("bottom-left")))),
                  Some(Branch("middle-right", right = Some(Leaf("bottom-right")))))

使用您给定的类层次结构,您将无法创建与所需的示例树完全相似的内容,因为分支只能接受左、右子树,而不能接受值(文本“top”)

如果您希望分支节点也有一个值,我将修改您的类层次结构,如下所示:

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](value: A, left: Option[Tree[A]] = None, right: Option[Tree[A]] = None) extends Tree[A]
val tree = Branch("top",
                  Some(Branch("middle-left", Some(Leaf("bottom-left")))),
                  Some(Branch("middle-right", right = Some(Leaf("bottom-right")))))
请注意子树的选项al性质,默认值为None,允许在不使用null的情况下丢失左或右子树

然后可以按如下方式生成示例树:

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](value: A, left: Option[Tree[A]] = None, right: Option[Tree[A]] = None) extends Tree[A]
val tree = Branch("top",
                  Some(Branch("middle-left", Some(Leaf("bottom-left")))),
                  Some(Branch("middle-right", right = Some(Leaf("bottom-right")))))
简短回答 你不能。数据结构的构建方式使其只能在叶中保存数据,而不能在内部节点中保存数据

长话短说 这里有一棵单子树。这棵树只能在其叶子中存储值,但它有一个非常好的特性:当值再次是一元树时(如果树中有一棵树),可以将结构展平,这样就可以再次得到一棵树

Haskell中的“证明”(因为类型类在Scala中有点奇怪)是一元的:

data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Monad Tree where
   return = Leaf
   Leaf a >>= f = f a
   Branch l r >>= f = Branch (l >>= f) (r >>= f)
好吧,这不是一个完整的证明,除非我证明mondic定律适用于这个类型的类。但是我想你可以看到这个想法。

简短回答 你不能。数据结构的构建方式使其只能在叶中保存数据,而不能在内部节点中保存数据

长话短说 这里有一棵单子树。这棵树只能在其叶子中存储值,但它有一个非常好的特性:当值再次是一元树时(如果树中有一棵树),可以将结构展平,这样就可以再次得到一棵树

Haskell中的“证明”(因为类型类在Scala中有点奇怪)是一元的:

data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Monad Tree where
   return = Leaf
   Leaf a >>= f = f a
   Branch l r >>= f = Branch (l >>= f) (r >>= f)

好吧,这不是一个完整的证明,除非我证明mondic定律适用于这个类型的类。但是我想你可以看到这个想法。

案例类节点[A](值:A,左:树[A],右:树[A])扩展了树[A];案例对象为空扩展树[无]
。这样,您就不需要这些选项了。或者保留这些选项,但是删除类型Leaf,只需要
case class Tree[+A](值:A,左:Option[Tree[A]],右:Option[Tree[A]])
-我还是喜欢空的。无论如何,同样的东西可能被表示为没有孩子的树枝或叶子,这听起来是不对的。@DidierDupont同意,删除叶子的案例是相当合理的。空的大小写也很好。或者
case类节点[A](值:A,左:树[A],右:树[A])扩展树[A];案例对象为空扩展树[无]
。这样,您就不需要这些选项了。或者保留这些选项,但是删除类型Leaf,只需要
case class Tree[+A](值:A,左:Option[Tree[A]],右:Option[Tree[A]])
-我还是喜欢空的。无论如何,同样的东西可能被表示为没有孩子的树枝或叶子,这听起来是不对的。@DidierDupont同意,删除叶子的案例是相当合理的。空箱子也很不错。不,那不是手指树。在手指树上的“手指”指的是左边和右边的“叶子”的叶子,它们可以比中间的叶子更快地访问。不,那不是指树。在手指树上的“手指”指的是树的左右两端的叶子,它们可以比中间的叶子更快地进入。