Reputation: 41939
How can I instantiate a Tree per the below trait and case classes?
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]
Source: Functional Programming in Scala
Example: How would I code the following tree of type String
?
"top"
/ \
"middle-left" "middle-right"
/ \
"bottom-left" "bottom-right"
Upvotes: 1
Views: 1053
Reputation: 8932
You can't. Your data structure is built in a way that it can only hold data in the leafs, but not in the inner nodes.
You have here a monadic tree. This tree can only store values in its leafs, but it has a very nice property: When the value is again a monadic tree (sou you have a tree in a tree), you can flatten the construct out, so you can get a tree again.
"Proof" in Haskell (because type classes are a little bit strange in Scala) for being monadic:
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)
OK, it's not a full proof, until I show that the mondic laws hold for this type class. But I think you can see the idea.
Upvotes: 2
Reputation: 15074
With the class hierarchy as you have given it you wouldn't be able to create something properly resembling the example tree you want, because Branch can only accept left and right sub-trees, not a value (the text "top").
If you want the branch nodes to also have a value, I would modify your class hierarchy as follows:
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]
Note the Option-al nature of the sub-trees, with a default of None, allowing for missing left or right sub-trees without resorting to nulls.
Your example tree could then be generated as follows:
val tree = Branch("top",
Some(Branch("middle-left", Some(Leaf("bottom-left")))),
Some(Branch("middle-right", right = Some(Leaf("bottom-right")))))
Upvotes: 2