Update: The answer is below the address of the earlier version of the question, but mostly still relevant.
First of all, your code will not work as it is. You can either make everything unchanged, or go with dispersion annotations in the original article. For simplicity, I will take an invariant route (see here for a full example), but I also just confirmed that the version in the document will work on 2.10.2.
First answer your first question: your binary tree type is isomorphic to BinTree[Int] . Before we can show this, we need a functor for our pair type:
implicit object pairFunctor extends Functor[Pair] { def map[A, B](a: Pair[A])(f: A => B) = (f(a._1), f(a._2)) }
Now we can use the resume , which we will need to convert from BinTree back to T :
def from(tree: T): BinTree[Int] = tree match { case L(i) => Done(i) case F((l, r)) => More[Pair, Int]((from(l), from(r))) } def to(tree: BinTree[Int]): T = tree.resume match { case Left((l, r)) => F((to(l), to(r))) case Right(i) => L(i) }
Now we can define your example tree:
var z = 0 def f(i: Int): T = if (i > 0) F((f(i - 1), f(i - 1))) else { z = z + 1; L(z) } val tree = f(3)
We demonstrate our isomorphism and monad for BinTree , replacing each leaf value with a tree containing its predecessor and successor:
val newTree = to( from(tree).flatMap(i => More[Pair, Int]((Done(i - 1), Done(i + 1)))) )
After some reformatting, the result will look like this:
F(( F(( F(( F((L(0), L(2))), F((L(1), L(3))) )), F(( F((L(2), L(4))), F((L(3), L(5))) )), ...
And so on, as expected.
For your second question: if you want to do the same for rosewood, you just replace the pair with a list (or stream). You will need to provide a functor instance for lists, as it was above for pairs, and then you have a tree with Done(x) representing the leaves and More(xs) for the branches.
Your type requires a map for the for -comprehension syntax. Fortunately, you can write map in terms of flatMap and Done - just add the following to the Free definition:
def map[B](f: A => B): Free[S, B] = this.flatMap(f andThen Done.apply)
Now the following is the same as newTree above:
val newTree = to( for { i <- from(tree) m <- More[Pair, Int]((Done(i - 1), Done(i + 1))) } yield m )
The same will work with the rosewood tree Free[List, _] .