In the code shown below, how can I convert EmptyTree
to object (Singleton) ?
trait Tree[T] {
def contains(num: T): Boolean
def inc( num: T )
You have to fix the generic argument because that's the only time you can provide it:
scala> trait A[T]
defined trait A
scala> object B extends A[Int]
defined object B
Obviously you want to reuse EmptyTree
for all types of T
, so instead of defining A[SOMETYPE]
for each type just use bottom type Nothing
:
scala> object B extends A[Nothing]
defined object B
This object can be used with any tree.
That's exactly how Option[T]
is implemented in Scala. Here is how None
is defined:
case object None extends Option[Nothing]
If keeping generics, also there is an option to add empty factory - like it's done for Map and Vector. Off course, with such an implementation it will not be a unique instance object for every creation, but when using inc
method, it will not produce new objects, it will just reference itself.
object DataTree {
def empty[T <% Ordered[T]] = new Tree[T] {
def contains(num: T):Boolean = false
def inc(num: T): Tree[T] = {
new DataTree(num, this, this)
}
override def toString = "."
}
}
So you can instantiate it as following:
val t = new DataTree(20, DataTree.empty[Int], DataTree.empty[Int])
Let me detalize Alexey's answer. Here is full implementation with some code style improvements:
First define your trait with aknowledgment of its covariance:
trait Tree[+T] {
def contains[U >: T : Ordering](num: U): Boolean
def inc[U >: T : Ordering](num: U): Tree[U]
}
Next define your subtype-of-all-trees object
case object EmptyTree extends Tree[Nothing] {
def contains[U >: Nothing : Ordering](num: U): Boolean = false
def inc[U >: Nothing : Ordering](num: U): Tree[U] =
DataTree(num, EmptyTree, EmptyTree)
override def toString = "."
}
Now change your general case implementation:
case class DataTree[T: Ordering](x: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
import Ordering.Implicits._
def contains[U >: T : Ordering](num: U): Boolean =
if (num < x) left.contains(x)
else if (num > x) right.contains(x)
else true
def inc[U >: T : Ordering](num: U): Tree[U] =
if (num < x) DataTree(x, left.inc(num), right)
else if (num > x) DataTree(x, left, right.inc(num))
else this
override def toString = "{" + left + x + right + "}"
}
You could be a little bit frustrated since I replaced your Ordered
with Ordering
, but you should know that view bounds are deprecated