Created
April 20, 2011 21:51
-
-
Save ppurang/932958 to your computer and use it in GitHub Desktop.
In 2.9.0 RC0 issues encountered while defining a map using fold on BTree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Given a map defined like: | |
def map[A, B](f: A => B)(btree: BTree[A]): BTree[B] = | |
fold((_:A) => Leaf(f(_)).asInstanceOf[BTree[B]])((x:BTree[B]) => (y:BTree[B]) => Fork(x,y))(btree) | |
when applied on a tree ((1 2) (3 4)) | |
map((x:Int) => x*2)(BTree(1 :: 2 :: 3 :: 4 :: Nil)) | |
results in ((<function1> <function1>) (<function1> <function1>)) | |
*/ | |
sealed trait BTree[+A] | |
case class Leaf[+A](a: A) extends BTree[A] { | |
override def toString = a.toString | |
} | |
case class Fork[+A](left: BTree[A], right: BTree[A]) extends BTree[A] { | |
override def toString = "(" + left + " " + right + ")" | |
} | |
//but when it is defined like | |
object BTree { | |
def map[A, B](f: A => B)(btree: BTree[A]): BTree[B] = | |
fold((x:A) => Leaf(f(x)).asInstanceOf[BTree[B]])((x:BTree[B]) => (y:BTree[B]) => Fork(x,y))(btree) | |
def fold[A,B](f: A => B)(g: B => B => B)(btree: BTree[A]): B = btree match { | |
case Leaf(x) => f(x) | |
case Fork(x,y) => g(fold(f)(g)(x))(fold(f)(g)(y)) | |
} | |
def apply[A](list: List[A]): BTree[A] = { | |
val m: Int = list.length / 2 | |
m match { | |
case 0 => Leaf(list.head) | |
case _ => val tuple = list.splitAt(m) | |
Fork(BTree(tuple._1), BTree(tuple._2)) | |
} | |
} | |
//todo varargs apply | |
} | |
//and applied like before i.e. map((x:Int) => x*2)(BTree(1 :: 2 :: 3 :: 4 :: Nil)) | |
//results in ((2 4) (6 8)) -- the expected outcome | |
//also notice the hack in the definition Leaf(f(x)).asInstanceOf[BTree[B]] | |
//without it the compiler complains that Fork(x,y) is not correct because a Leaf's expected. | |
//I wanted to give the compiler a type hint so that it wouldn't complain | |
//but that was turning out to be rather complicated (perhaps use :type to find it out in the REPL) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So, the reason the first one returns weird results is because of this:
This actually means the same as the following:
As for the cast, you should be able to replace that with a simple attribution:
Unfortunately, there's no way to allow the type inference to figure this out. Local inference is just too limited.