When combining collections, 2 cases are possible: a union with an empty collection (it will give the 1st collection) and a non-empty one.
To explain the merging process with a non-empty collection, consider the incl (x: Tweet) method. Each of its calls recursively rearranges the left or right subtree, depending on the argument.
The union method (that: TweetSet) recursively merges one of the subtrees of the current tree with the tree that, then the other subtree also merges with the result, and finally adds a root to the resulting tree.
For clarification by example, you can add methods to visualize the result.
class Tweet(val text: String) class Empty extends TweetSet { .... override def toString = "." } class NonEmpty(elem: Tweet, left: TweetSet, right: TweetSet) extends TweetSet { override def union(that: TweetSet): TweetSet = { val res = (left union (right union that)).incl(elem) println(s"union ${this} and ${that} is " + res) res } ... override def toString = "{" + left + "," + right + "}" }
Next, the test code itself:
object ts { val emp = new Empty //> emp : Empty = . def generTweet = new Tweet(scala.util.Random.nextString(10)) //> generTweet: => Tweet def generTweets(n: Int) = for (i <- 0 until n) yield generTweet //> generTweets: (n: Int)scala.collection.immutable.IndexedSeq[Tweet] def generTweetSet(n: Int, acc: TweetSet = new Empty): TweetSet = if (n == 0) acc else generTweetSet(n-1, acc.incl(generTweet)) //> generTweetSet: (n: Int, acc: TweetSet)TweetSet val nonEmpty1 = generTweetSet(1) //> nonEmpty1 : TweetSet = {.,.} val nonEmpty2 = generTweetSet(1) //> nonEmpty2 : TweetSet = {.,.} nonEmpty1 union nonEmpty2 //> union {.,.} and {.,.} is {.,{.,.}} //| res0: TweetSet = {.,{.,.}} val nonEmpty3 = generTweetSet(2) //> nonEmpty3 : TweetSet = {{.,.},.} nonEmpty1 union nonEmpty3 //> union {.,.} and {{.,.},.} is {{.,.},{.,.}} //| res1: TweetSet = {{.,.},{.,.}} nonEmpty3 union nonEmpty1 //> union {.,.} and {.,.} is {{.,.},.} //| union {{.,.},.} and {.,.} is {{.,{.,.}},.} //| res2: TweetSet = {{.,{.,.}},.} val nonEmpty4 = generTweetSet(2) //> nonEmpty4 : TweetSet = {.,{.,.}} nonEmpty3 union nonEmpty4 //> union {.,.} and {.,{.,.}} is {.,{{.,.},.}} //| union {{.,.},.} and {.,{.,.}} is {.,{{.,{.,.}},.}} //| res3: TweetSet = {.,{{.,{.,.}},.}} }