I'm trying to implement a tail-recursive foldLeft function for a regular shaped tree. The exercise comes from the book, "The Science of Functional Programming," in exercise 3.3.5.3.
Until now, I was able to do the exercises but I don't know what I'm missing in this one.
There's is a definition for the regular shaped tree:
sealed trait RTree[A]
final case class Leaf[A](x: A) extends RTree[A]
final case class Branch[A](xs: RTree[(A,A)]) extends RTree[A]
The method signature and expected result:
#tailrec
def foldLeft[A,R](t: RTree[A])(init: R)(f: (R,A)=>R): R= ???
foldLeft(Branch(Branch(Leaf(((1,2),(3,4))))))(0)(_+_)
//10
The biggest problem so far is that I don't know how to match and access the element inside the case class of Branch. I can only match the Leaf and Branch (and not the leaf's inside a branch) and because of that the recursion has no end.
Not sure if this helps, but for now I have only NON tail-recursive implementation.
def foldLeft[A, R](t: RTree[A])(init: R)(f: (R, A) => R): R = {
t match {
case Leaf(value) => f(init, value)
case Branch(tree) =>
foldLeft(tree)(init) {
case (result, (left, right)) => f(f(result, left), right)
}
}
}
UPDATE: As was said in comments section to this answer this is actually tail rec implementation, excuse me, for confusing you.
Related
I am writing a filter function in Scala and although I feel good about what I am trying to do I can not figure out why it will not recognize my List or what this bug is telling me. I have tried editing the syntax but nothing seems to fix it
sealed trait List[+A]
case object Empty extends List[Nothing]
case class Cons[A]( x : A, xs : List[A]) extends List[A]
def filter[A](f: A => Boolean, list: List[A]): List[A] =
for {
a <- list
if (f(a))
} yield a
<console>:93: error: value filter is not a member of List[A]
a <- list
Check out code here
So, if we first understand that for comprehensions are sugar syntax for map, flatMap and filter. Then we can see that your attempt of defining filter is equivalent to:
list.filter(a => f(a))
Which obviously doesn't make sense.
You can not define filter in terms of filter...
Well, you actually can, that is what recursion is all about, and actually that is the correct way of solving the problem.
With the extra help of pattern matching.
So a recursive function is the best way to process a recursive data structure like List.
The process is actually quite straight forward, we need to figure out what to do in the base case and what to do in the recursive case (which probably will require a recursive call).
(note: I changed the function signature, this new signature allows better syntax and better type inference)
/** Returns a new list with only the elements that satisfied the predicate. **/
def filter[A](list: List[A])(p: A => Boolean): List[A] = list match {
case Empty => ??? // Base case. Tip: tink in what is the filter of an empty list.
case Cons(a, tail) => ??? // Recursive case. Tip: you probably will need to call the function recursively.
}
Once you fill the holes, you will have a proper filter function. But, we got a problem, since this is a recursive solution, trying to filter a very big list will result in a StackOverflowError which is not ideal, so what can we do?
Tail-Recursion to the rescue!
The idea is simple, we need to keep an accumulator for holding intermediate values.
(note: it is usually a good idea to keep the tail function as an inner function)
/** Returns a new list with only the elements that satisfied the predicate. **/
def filter[A](list: List[A])(p: A => Boolean): List[A] = {
#annotation.tailrec
def loop(remaining: List[A], acc: ???): List[A] =
remaining match {
case Cons(a, as) => ??? // Recursive case.
case Empty => ??? // Base case, we are done! Tip: Is the output correct?
}
loop(remaining = list, acc = ???)
}
Once you fill the holes, you will have a good filter function.
(Final note: Following a technique called type tetris probably will help to get the correct solution)
First of all, I have a suggestions for you -
Don't use semicolons in Scala.
Use camelCase for variable names in Scala. (You can use CAPITAL_SNAKE_CASE for constants though).
Use CapitalCamelCase for trait, class and object names.
Now, you are naming your paramter as List which conflicts with class List.
So, your code need to be changed to this,
def filter[A](f: A => Boolean, list: List[A]): List[A] =
for {
a <- list
if (f(a))
} yield a
// use the defined method to filter the list
filter[Int](i => i > 2, List(1,2,3,4))
I am writing a filter function in Scala and although I feel good about what I am trying to do I can not figure out why it will not recognize my List or what this bug is telling me. I have tried editing the syntax but nothing seems to fix it
sealed trait List[+A]
case object Empty extends List[Nothing]
case class Cons[A]( x : A, xs : List[A]) extends List[A]
def filter[A](f: A => Boolean, list: List[A]): List[A] =
for {
a <- list
if (f(a))
} yield a
<console>:93: error: value filter is not a member of List[A]
a <- list
Check out code here
So, if we first understand that for comprehensions are sugar syntax for map, flatMap and filter. Then we can see that your attempt of defining filter is equivalent to:
list.filter(a => f(a))
Which obviously doesn't make sense.
You can not define filter in terms of filter...
Well, you actually can, that is what recursion is all about, and actually that is the correct way of solving the problem.
With the extra help of pattern matching.
So a recursive function is the best way to process a recursive data structure like List.
The process is actually quite straight forward, we need to figure out what to do in the base case and what to do in the recursive case (which probably will require a recursive call).
(note: I changed the function signature, this new signature allows better syntax and better type inference)
/** Returns a new list with only the elements that satisfied the predicate. **/
def filter[A](list: List[A])(p: A => Boolean): List[A] = list match {
case Empty => ??? // Base case. Tip: tink in what is the filter of an empty list.
case Cons(a, tail) => ??? // Recursive case. Tip: you probably will need to call the function recursively.
}
Once you fill the holes, you will have a proper filter function. But, we got a problem, since this is a recursive solution, trying to filter a very big list will result in a StackOverflowError which is not ideal, so what can we do?
Tail-Recursion to the rescue!
The idea is simple, we need to keep an accumulator for holding intermediate values.
(note: it is usually a good idea to keep the tail function as an inner function)
/** Returns a new list with only the elements that satisfied the predicate. **/
def filter[A](list: List[A])(p: A => Boolean): List[A] = {
#annotation.tailrec
def loop(remaining: List[A], acc: ???): List[A] =
remaining match {
case Cons(a, as) => ??? // Recursive case.
case Empty => ??? // Base case, we are done! Tip: Is the output correct?
}
loop(remaining = list, acc = ???)
}
Once you fill the holes, you will have a good filter function.
(Final note: Following a technique called type tetris probably will help to get the correct solution)
First of all, I have a suggestions for you -
Don't use semicolons in Scala.
Use camelCase for variable names in Scala. (You can use CAPITAL_SNAKE_CASE for constants though).
Use CapitalCamelCase for trait, class and object names.
Now, you are naming your paramter as List which conflicts with class List.
So, your code need to be changed to this,
def filter[A](f: A => Boolean, list: List[A]): List[A] =
for {
a <- list
if (f(a))
} yield a
// use the defined method to filter the list
filter[Int](i => i > 2, List(1,2,3,4))
I have a function in Scala that matches different case classes, but executes the same code on every match. Is there a possibility to “fallthrough”? Or a other nice way to write the code bellow without code duplication and without defining a function?
symbol match {
case Times(a,b) => //some code using a and b
case Plus(a,b) => //same code as above
case Div(a,b) => //again same code as above
}
This is a pretty similar too the question "Match "fallthrough": executing same piece of code for more than one case?" with the difference that I'm intressted in matching with case classes.
You could write your own extractor that combines the three cases and turns them into a tuple:
object BinOp {
def unapply(op: Op) = op match {
case Times(a, b) => Some(a, b)
case Plus(a, b) => Some(a, b)
case Div(a, b) => Some(a, b)
}
}
symbol match {
case BinOp(a, b) =>
}
No, falltroughs are prohibited in Scala since they are a common source of bugs in other languages. You have two three possibilites:
factor out everything that is identical in a function
try to use less specific matching, i.e., by using wildcards. In your example, this could also mean to introduce a superclass BinaryOperation which gives you the possibility of a more generic match. Note that due to case class inheritance restrictions, you would have to rely on using the fields of this superclass instead of having a super case class.
follow Mirko Stocker's nice suggestions of writing a specific extractor.
I see two possible solutions to your problem
1) unapply
Extending on M. Stocker's answer, you could organize your data like so:
trait Op
trait BinaryOp extends Op {
def a: Int
def b: Int
}
object BinaryOp {
def unapply(op: Op) = op match {
case x: BinaryOp => Some((x.a, x.b))
case _ => None
}
}
case class Times(a: Int, b: Int) extends BinaryOp
case class Plus(a: Int, b: Int) extends BinaryOp
case class Div(a: Int, b: Int) extends BinaryOp
Usage:
symbol match {
case BinaryOp(a, b) => f(a, b)
case _ => //...
}
2) Product
All case classes extends the Product trait
This allows you to do the following matching:
symbol match {
case p: Product if p.productArity == 2 => {
val a = p.productElement(0) //this has type Any, so a cast may be necessary
val b = p.productElement(1)
f(a, b)
}
}
The second case is more generic, but it is also type-unsafe. I recommend the first solution.
Is it possible to generically replace arguments in a case class? More specifically, say I wanted a substitute function that received a "find" case class and a "replace" case class (like the left and right sides of a grammar rule) as well as a target case class, and the function would return a new case class with arguments of the find case class replaced with the replace case class? The function could also simply take a case class (Product?) and a function to be applied to all arguments/products of the case class.
Obviously, given a specific case class, I could use unapply and apply -- but what's the best/easiest/etc way to generically (given any case class) write this sort of function?
I'm wondering if there is a good solution using Scala 2.10 reflection features or Iso.hlist from shapeless.
For example, what I really want to be able to do is, given classes like the following...
class Op[T]
case class From(x:Op[Int]) extends Op[Int]
case class To(x:Op[Int]) extends Op[Int]
case class Target(a:Op[Int], b:Op[Int]) extends ...
// and lots of other similar case classes
... have a function that can take an arbitrary case class and return a copy of it with any elements of type From replaced with instances of type To.
If you'll pardon the plug, I think you'll find that the rewriting component of our Kiama language processing library is perfect for this kind of purpose. It provides a very powerful form of strategic programming.
Here is a complete solution that rewrites To's to From's in a tree made from case class instances.
import org.kiama.rewriting.Rewriter
class Op[T]
case class Leaf (i : Int) extends Op[Int]
case class From (x : Op[Int]) extends Op[Int]
case class To (x : Op[Int]) extends Op[Int]
case class Target1 (a : Op[Int], b : Op[Int]) extends Op[Int]
case class Target2 (c : Op[Int]) extends Op[Int]
object Main extends Rewriter {
def main (args : Array[String]) {
val replaceFromsWithTos =
everywhere {
rule {
case From (x) => To (x)
}
}
val t1 = Target1 (From (Leaf (1)), To (Leaf (2)))
val t2 = Target2 (Target1 (From (Leaf (3)), Target2 (From (Leaf (4)))))
println (rewrite (replaceFromsWithTos) (t1))
println (rewrite (replaceFromsWithTos) (t2))
}
}
The output is
Target1(To(Leaf(1)),To(Leaf(2)))
Target2(Target1(To(Leaf(3)),Target2(To(Leaf(4)))))
The idea of the replaceFromsWithTos value is that the rule construct lifts a partial function to be able to operate on any kind of value. In this case the partial function is only defined at From nodes, replacing them with To nodes. The everywhere combinator says "apply my argument to all nodes in the tree, leaving unchanged places where the argument does not apply.
Much more can be done than this kind of simple rewrite. See the main Kiama rewriting documentation for the gory detail, including links to some more examples.
I experimented a bit with shapeless and was able to come up with the following, relatively generic way of converting one case class into another:
import shapeless._ /* shapeless 1.2.3-SNAPSHOT */
case class From(s: String, i: Int)
case class To(s: String, i: Int)
implicit def fromIso = Iso.hlist(From.apply _, From.unapply _)
implicit def toIso = Iso.hlist(To.apply _, To.unapply _)
implicit def convert[A, B, L <: HList]
(a: A)
(implicit srcIso: Iso[A, L],
dstIso: Iso[B, L])
: B =
dstIso.from(srcIso.to(a))
val f1 = From("Hi", 7)
val t1 = convert(f1)(fromIso, toIso)
println("f1 = " + f1) // From("Hi", 7)
println("t1 = " + t1) // To("Hi", 7)
However, I was not able to get the implicits right. Ideally,
val t1: To = f1
would be sufficient, or maybe
val t1 = convert(f1)
Another nice improvement would be to get rid of the need of having to explicitly declare iso-implicits (fromIso, toIso) for each case class.
I don't think you'll really find a better way than just using unapply/apply through pattern matching:
someValue match {
case FindCaseClass(a, b, c) => ReplaceCaseClass(a, b, c)
// . . .
}
You have to write out the rules to associate FindCaseClass with ReplaceCaseClass somehow, and although you might be able to do it a little more succinctly by somehow just using the names, this has the added benefit of also checking the number and types of the case class fields at compile time to make sure everything matches just right.
There is probably some way to do this automatically using the fact that all case classes extend Product, but the fact that productElement(n) returns Any might make it a bit of a pain—I think that's where reflection would have to come in. Here's a little something to get you started:
case class From(i: Int, s: String, xs: Seq[Nothing])
case class To(i: Int, s: String, xs: Seq[Nothing])
val iter = From(5,"x",Nil).productIterator
val f = To.curried
iter.foldLeft(f: Any) { _.asInstanceOf[Any => Any](_) }
// res0: Any = To(5,x,List())
But really, I think you're better off with the pattern-matching version.
Edit: Here is a version with the relavent code refactored into a method:
case class From(i: Int, s: String, xs: Seq[Nothing])
case class To(i: Int, s: String, xs: Seq[Nothing])
type Curryable = { def curried: _ => _ }
def recase(from: Product, to: Curryable) = {
val iter = from.productIterator
val f = to.curried
iter.foldLeft(f: Any) { _.asInstanceOf[Any => Any](_) }
}
recase(From(5,"x",Nil), To)
// res0: Any = To(5,x,List())
For a homework assignment I wrote some scala code in which I have the following classes and object (used for modeling a binary tree):
object Tree {
def fold[B](t: Tree, e: B, n: (Int, B, B) => B): B = t match {
case Node(value, l, r) => n(value,fold(l,e,n),fold(r,e,n))
case _ => e
}
def sumTree(t: Tree): Tree =
fold(t, Nil(), (a, b: Tree, c: Tree) => {
val left = b match {
case Node(value, _, _) => value
case _ => 0
}
val right = c match {
case Node(value, _, _) => value
case _ => 0
}
Node(a+left+right,b,c)
})
}
abstract case class Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
case class Nil extends Tree
My question is about the sumTree function which creates a new tree where the nodes have values equal to the sum of the values of its children plus it's own value.
I find it rather ugly looking and I wonder if there is a better way to do this. If I use recursion which works top-down this would be easier, but I could not come up with such a function.
I have to implement the fold function, with a signature as in the code, to calculate sumTree
I got the feeling this can be implemented in a better way, maybe you have suggestions?
First of all, I believe and if I may say so, you've done a very good job. I can suggest a couple of slight changes to your code:
abstract class Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
case object Nil extends Tree
Tree doesn't need to be a case-class, besides using a case-class as non-leaf node is deprecated because of possible erroneous behaviour of automatically generated methods.
Nil is a singleton and best defined as a case-object instead of case-class.
Additionally consider qualifying super class Tree with sealed. sealed tells compiler that the class can only be inherited from within the same source file. This lets compiler emit warnings whenever a following match expression is not exhaustive - in other words doesn't include all possible cases.
sealed abstract class Tree
The next couple of improvement could be made to the sumTree:
def sumTree(t: Tree) = {
// create a helper function to extract Tree value
val nodeValue: Tree=>Int = {
case Node(v,_,_) => v
case _ => 0
}
// parametrise fold with Tree to aid type inference further down the line
fold[Tree](t,Nil,(acc,l,r)=>Node(acc + nodeValue(l) + nodeValue(r) ,l,r))
}
nodeValue helper function can also be defined as (the alternative notation I used above is possible because a sequence of cases in curly braces is treated as a function literal):
def nodeValue (t:Tree) = t match {
case Node(v,_,_) => v
case _ => 0
}
Next little improvement is parametrising fold method with Tree (fold[Tree]). Because Scala type inferer works through the expression sequentially left-to-right telling it early that we're going to deal with Tree's lets us omit type information when defining function literal which is passed to fold further on.
So here is the full code including suggestions:
sealed abstract class Tree
case class Node(value: Int, left: Tree, right: Tree) extends Tree
case object Nil extends Tree
object Tree {
def fold[B](t: Tree, e: B, n: (Int, B, B) => B): B = t match {
case Node(value, l, r) => n(value,fold(l,e,n),fold(r,e,n))
case _ => e
}
def sumTree(t: Tree) = {
val nodeValue: Tree=>Int = {
case Node(v,_,_) => v
case _ => 0
}
fold[Tree](t,Nil,(acc,l,r)=>Node(acc + nodeValue(l) + nodeValue(r) ,l,r))
}
}
The recursion you came up with is the only possible direction that lets you traverse the tree and produce a modified copy of the immutable data structure. Any leaf nodes have to be created first before being added to the root, because individual nodes of the tree are immutable and all objects necessary to construct a node have to be known before the construction: leaf nodes need to be created before you can create root node.
As Vlad writes, your solution has about the only general shape you can have with such a fold.
Still there is a way to get rid of the node value matching, not only factor it out. And personally I would prefer it that way.
You use match because not every result you get from a recursive fold carries a sum with it. Yes, not every Tree can carry it, Nil has no place for a value, but your fold is not limited to Trees, is it?
So let's have:
case class TreePlus[A](value: A, tree: Tree)
Now we can fold it like this:
def sumTree(t: Tree) = fold[TreePlus[Int]](t, TreePlus(0, Nil), (v, l, r) => {
val sum = v+l.value+r.value
TreePlus(sum, Node(sum, l.tree, r.tree))
}.tree
Of course the TreePlus is not really needed as we have the canonical product Tuple2 in the standard library.
Your solution is probably more efficient (certainly uses less stack), but here's a recursive solution, fwiw
def sum( tree:Tree):Tree ={
tree match{
case Nil =>Nil
case Tree(a, b, c) =>val left = sum(b)
val right = sum(c)
Tree(a+total(left)+total(right), left, right)
}
}
def total(tree:Tree):Int = {
tree match{
case Nil => 0
case Tree(a, _, _) =>a
}
You've probably turned in your homework already, but I think it's still worth pointing out that the way your code (and the code in other people's answers) looks like is a direct result of how you modeled the binary trees. If, instead of using an algebraic data type (Tree, Node, Nil), you had gone with a recursive type definition, you wouldn't have had to use pattern matching to decompose your binary trees. Here's my definition of a binary tree:
case class Tree[A](value: A, left: Option[Tree[A]], right: Option[Tree[A]])
As you can see there's no need for Node or Nil here (the latter is just glorified null anyway - you don't want anything like this in your code, do you?).
With such definition, fold is essentially a one-liner:
def fold[A,B](t: Tree[A], z: B)(op: (A, B, B) => B): B =
op(t.value, t.left map (fold(_, z)(op)) getOrElse z, t.right map (fold(_, z)(op)) getOrElse z)
And sumTree is also short and sweet:
def sumTree(tree: Tree[Int]) = fold(tree, None: Option[Tree[Int]]) { (value, left, right) =>
Some(Tree(value + valueOf(left, 0) + valueOf(right, 0), left , right))
}.get
where valueOf helper is defined as:
def valueOf[A](ot: Option[Tree[A]], df: A): A = ot map (_.value) getOrElse df
No pattern matching needed anywhere - all because of a nice recursive definition of binary trees.