Scala | Folding in binary tree - scala

I implemented a fold method in my scala code. I can use it to determine the size and the depth of the tree.
Now I'd like to implement the methods max and map which should work like here.
The difference is, that the value is saved in the branch instead of the leaf.
Here's my code so far:
sealed trait Tree[+A] {
def size(): Int = fold(this)(() => 1)((l, r, v) => 1 + l + r)
def depth(): Int = fold(this)(() => 0)((left: Int, right: Int, v: A) => 1 + (left max right))
def fold[X, B](t: Tree[X])(f: () => B)(g: (B, B, X) => B): B = t match {
case Leaf() => f()
case Branch(left, right, v) => g(fold(left)(f)(g), fold(right)(f)(g), v)
}
}
case class Leaf[A]() extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A], v: A) extends Tree[A]
Can anybody help me with that?

Firstly, you can put fold to companion object of Tree (since fold doesn't use this i.e. is "static").
Secondly, start with implementing map for your case
def map[A,B](t: Tree[A])(f: A => B): Tree[B] = t match {
case Leaf() => ???_1
case Branch(l, r, v) => ???_2 // here l, r are Tree[A]'s i.e. subtrees of t
}
looking how it's implemented for trees with values in leaves.
Then replace this implementation with the one using fold
def map[B](f: A => B): Tree[B] =
fold[A, Tree[B]](this)(() => ???_1_)((l: Tree[B], r: Tree[B], v: A) => ???_2_))
// here l, r are Tree[B]'s i.e. results of map for subtrees
???_1_ and ???_2_ are ???_1, ???_2, where you replace recursive call of map with l, r, which are results of the recursive call. So ???_1_ is exactly ???_1.

Related

Programming a state monad in Scala

The theory of how a state monad looks like I borrow from Philip Wadler's Monads for Functional Programming:
type M a = State → (a, State)
type State = Int
unit :: a → M a
unit a = λx. (a, x)
(*) :: M a → (a → M b) → M b
m * k = λx.
let (a, y) = m x in
let (b, z) = k a y in
(b, z)
The way I would like to use a state monad is as follows:
Given a list L I want different parts of my code to get this list and update this list by adding new elements at its end.
I guess the above would be modified as:
type M = State → (List[Data], State)
type State = List[Data]
def unit(a: List[Data]) = (x: State) => (a,x)
def star(m: M, k: List[Data] => M): M = {
(x: M) =>
val (a,y) = m(x)
val (b,z) = k(a)(y)
(b,z)
}
def get = ???
def update = ???
How do I fill in the details, i.e.?
How do I instantiate my hierarchy to work on a concrete list?
How do I implement get and update in terms of the above?
Finally, how would I do this using Scala's syntax with flatMap and unit?
Your M is defined incorrectly. It should take a/A as a parameter, like so:
type M[A] = State => (A, State)
You've also missed that type parameter elsewhere.
unit should have a signature like this:
def unit[A](a: A): M[A]
star should have a signature like this:
def star[A, B](m: M[A], k: A => M[B]): M[B]
Hopefully, that makes the functions more clear.
Your implementation of unit was pretty much the same:
def unit[A](a: A): M[A] = x => (a, x)
However, in star, the parameter of your lambda (x) is of type State, not M, because M[B] is basically State => (A, State). The rest you got right:
def star[A, B](m: M[A])(k: A => M[B]): M[B] =
(x: State) => {
val (a, y) = m(x)
val (b, z) = k(a)(y)
(b, z)
}
Edit: According to #Luis Miguel Mejia Suarez:
It would probably be easier to implement if you make your State a class and define flatMap inside it. And you can define unit in the companion object.
He suggested final class State[S, A](val run: S => (A, S)), which would also allow you to use infix functions like >>=.
Another way to do it would be to define State as a type alias for a function S => (A, S) and extend it using an implicit class.
type State[S, A] = S => (A, S)
object State {
//This is basically "return"
def unit[S, A](a: A): State[S, A] = s => (a, s)
}
implicit class StateOps[S, A](private runState: S => (A, S)) {
//You can rename this to ">>=" or "flatMap"
def *[B](k: A => State[S, B]): State[S, B] = s => {
val (a, s2) = runState(s)
k(a)(s2)
}
}
If your definition of get is
set the result value to the state and leave the state unchanged
(borrowed from Haskell Wiki), then you can implement it like this:
def get[S]: State[S, S] = s => (s, s)
If you mean that you want to extract the state (in this case a List[Data]), you can use execState (define it in StateOps):
def execState(s: S): S = runState(s)._2
Here's a terrible example of how you can add elements to a List.
def addToList(n: Int)(list: List[Int]): ((), List[Int]) = ((), n :: list)
def fillList(n: Int): State[List[Int], ()] =
n match {
case 0 => s => ((), s)
case n => fillList(n - 1) * (_ => addToList(n))
}
println(fillList(10)(List.empty)) gives us this (the second element can be extracted with execState):
((),List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))

Build List from binary tree inorder traversal using function "fold"

I'm learning Scala. Now I have this code snippet:
sealed abstract class BSTree {
def fold[A](init: A)(f: (A, Int) => A): A = this match {
case Empty => init
case Node(left, data, right) =>
val curInorder:A = f(left.fold(init)(f), data)
right.fold(curInorder)(f)
}
}
case object Empty extends BSTree
case class Node(left: BSTree, data: Int, right: BSTree) extends BSTree
My aim is to add another method toList in class BSTree, which is on top
of method fold and build a List from the binary tree's inorder traversal.
My current implementation is:
sealed abstract class BSTree {
def fold[A](init: A)(f: (A, Int) => A): = .....//code snippet skipped
def toList: List[Int] =
fold(Nil: List[Int])((xs: List[Int], hd)=> hd::xs).reverse
}
But I feel that building a List and then reversing it is ugly. Is there a more elegant approach?
Any hints are appreciated.
First of all, your fold is not tail recursive which for large input might result in StackOverflowException. I'd encourage you to try out and implement it on your own using Stack. For reference I'll place a sample implementation at the bottom of my post.
Secondly, as it was already mentioned in comments - you might want to use ListBuffer so that building your list is more efficient in reversed order (thus, there is no need to reverse it back).
Here's a one-liner:
def toList: List[Int] = fold(ListBuffer.empty[Int])(_ += _).toList
And the the reference for implementing tail-recursive fold:
def fold[B](init: B)(op: (B, A) => B): B = {
def go(stack: List[(A, Tree[A])], current: Tree[A], acc: B): B = (current, stack) match {
case (Empty, Nil) => acc
case (Empty, (d, r) :: xs) => go(xs, r, op(acc, d))
case (Node(l, d, r), _) => go((d, r) +: stack, l, acc)
}
go(Nil, this, init)
}
I find that simply using xs :+ hd instead of hd::xs puts the values in the correct order (depth-first, left-to-right).
val testTree: BSTree =
Node(Node(Empty, 0, Empty), 1, Node(Empty, 2, Node(Node(Empty, 3, Empty), 4, Empty)))
def toList(bSTree: BSTree): List[Int] =
bSTree.fold(List[Int]())((acc, next) => acc :+ next)
toList(testTree) // List(0,1,2,3,4)
My implementation above is O(n²). We can improve it to O(n) by using a ListBuffer, as per #dkim's comment, or we can use Vector and then convert to List when we're done.
Apart from simply fixing the toList method, we might ask why the result of using fold to implement toList didn't agree with our intuition (giving us a backwards list instead of a forwards list). One might point out that the fold signature for list matches the structure of the List class hierarchy.
abstract class List[+A] {
def fold[B](init: B)(step: (A, B) => B): B
}
case object Empty extends List[Nothing] {
def fold[B](init: B)(step: (A, B) => B): B = init
}
case class Cons[+A](head: A, tail: List[A]) extends List[A] {
def fold[B](init: B)(step: (A, B) => B): B =
step(head, tail.fold(init)(step))
}
Notice how the method signature of fold matches the class hierarchy, even down to the values that each implementing class holds. (Aside: For purposes of brevity, I am using a very naive implementation of fold that is neither efficient nor stack safe. Production implementations should be tail recursive or use a loop and a mutable buffer, but the point is that the method signature would be the same.)
We can do the same for your BSTree class, the fold signature would be:
abstract class BSTree {
def fold[A](withEmpty: A)(withNode: (A, Int, A) => A): A
}
Then toList would be tree.fold(List[Int]())((l, n, r) => l ++ List(n) ++ r). But again, use a buffer or Vector to get decent performance if you anticipate tree being even about 50 entries or so.

Scala pass a generic function into another generic function confusion

I'm implementing the List type in Scala when following a book.
Here's the definition of my List type:
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
All the later mentioned functions are defined in the companion object List in the same file
object List
I wrote foldLeft and foldRight as the following
def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match {
case Nil => z
case Cons(x, xs) => foldLeft(xs, f(z, x))(f)
}
def foldRight[A,B](l: List[A], z: B)(f: (A, B) => B): B = l match {
case Nil => z
case Cons(x, xs) => f(x, foldRight(xs, z)(f))
}
There's an exercise on the book, which is to implement foldLeft using foldRight. Here's my initial implementation
def foldLeftWithRight[A,B](l: List[A], z: B)(f: (B, A) => B): B = {
foldRight(l, z)((a: A, b: B) => f(b, a))
}
Then I think I should write another function to do the reverse arguments if I'm to implement foldRight using foldLeft. As follows:
def reverseArgs[A,B](f: (A, B) => B): (B, A) => B = {
(b: B, a: A) => f(a, b)
}
So I changed code of foldLeftWithRight to the following:
def foldLeftWithRight[A,B](l: List[A], z: B)(f: (B, A) => B): B = {
foldRight(l, z)(reverseArgs(f))
}
And IntelliJ is complaining about reverseArgs(f):
Type mismatch: expected (A, B) => B, actual (B, B) => B
When I try to compile the code, the error is the following:
Error:(21, 37) type mismatch;
found : (B, A) => B
required: (B, Any) => Any
foldRight(l, z)(reverseArgs(f))
An interesting observation is that when I use the reverseArgs on foldRightWithLeft, there's no problem at all:
def foldRightWithLeft[A,B](l: List[A], z: B)(f: (A, B) => B): B = {
foldLeft(l, z)(reverseArgs(f))
}
What is going on here?
If you rename type parameters of your reverseArgs function to X and Y, you'll get something like
def reverseArgs[X ,Y](f: (X, Y) => Y): (Y, X) => Y = ???
Type of f in foldLeftWithRight is (B, A) => B. Passing that to reverseArgs means that:
X = B
Y = A
Y = B
I guess Intellij infers from here that A = B and this is why it's complaining that (B, B) => B isn't (A, B) => B. Scalac decides that Y = Any instead, because it's the least upper bound of two potentially unrelated types.
Good solution here is to generalize more. Return type of reversed function does not have to be one of parameter types, so you can introduce another generic type for that:
def reverseArgs[X ,Y, Z](f: (X, Y) => Z): (Y, X) => Z = {
(b: Y, a: X) => f(a, b)
}

Scala: check combination of two variables

I want to check if two variables taken in any order can be paired into a specific pair. Basically the below, only it doesn't work because of type erasure at runtime
def combination[A,B](x: Any, y: Any): Option[(A, B)] =
(x, y) match {
case (a: A, b: B) => Some(a, b)
case (b: B, a: A) => Some(a, b)
case _ => None
Is there another way to do the same which would work...
Note, since it wasn't clear in your message, if you want to pattern-match against a pair of constants (a, b), you may want to consider back-ticks instead of what you're doing :
case (`a`, `b`) => Some(a, b)
On the other hand if you are trying to retrieve the elements of a pair of any values of type (A, B), in any order, you can do it for non-primitive types (i.e. subtypes of AnyRef) :
import scala.reflect.ClassTag
def combination[A, B](x: AnyRef, y: AnyRef)(implicit tagA: ClassTag[A], tagB: ClassTag[B]): Option[(A, B)] = (x, y) match {
case (a: A, b: B) => Some(a, b)
case (b: B, a: A) => Some(a, b)
case _ => None
}

Tail recursive functions for BinaryTree

I am stuck with implementing tail recursive foreach, reduce, map and toList functions for a very simple implementation of binary tree.
sealed trait Tree[+A]
case object EmptyTree extends Tree[Nothing]
case class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]
object Tree {
def apply[A]: Tree[A] = EmptyTree
def apply[A](value: A): Tree[A] = Node(value, EmptyTree, EmptyTree)
def apply[A](value: A, left: Tree[A], right: Tree[A]): Tree[A] = Node(value, left, right)
def foreach[A](tree: Tree[A], f: (A) => Unit): Unit = {
//#tailrec
def iter[A](tree: Tree[A], f: (A) => Unit): Unit = tree match {
case EmptyTree =>
case Node(v, l, r) =>
iter(l, f)
f(v)
iter(r, f)
}
iter(tree, f)
}
def reduce[A](tree: Tree[A], value: A, f: (A, A) => A): A = {
//#tailrec
def loop(tree: Tree[A], value: A): A = tree match {
case Node(v, l, r) => loop(l, f(loop(r, value), v))
case EmptyTree => value
}
loop(tree, value)
}
def map[A, B](tree: Tree[A], f: A => B): Tree[B] = {
//#tailrec
def iter[A](tree: Tree[A], f: A => B): Tree[B] = tree match {
case Node(v, l, r) => Node(f(v), iter(l, f), iter(r, f))
case EmptyTree => EmptyTree
}
iter(tree, f)
}
def toList[A](t: Tree[A]): List[A] = {
//#tailrec
def iter[A](t: Tree[A]): List[A] = t match {
case Node(v, l, r) => v :: iter(l) ::: iter(r)
case EmptyTree => List.empty
}
iter(t)
}
}
Code for testing:
val tree = Tree(1, Tree(2, Tree(3), Tree(4)), Tree(5, Tree(6), Tree(7)))
Tree.foreach(tree, (x: Int) => println(x))
Tree.reduce(tree, 0, (x: Int, y: Int) => x + y)
Tree.map(tree, (x: Int) => x + 1)
Tree.toList(tree)
I cant use #tailrec attribute because as you can see, recursive calls are not the last calls in a function, and I do not know how to rewrite it because there are several calls in one function, for example
v :: iter(l) ::: iter(r)
I know that I can use accumulator for inner recursive functions but how I should use it in case of several calls ?
Thanks in advance.
Updated:
def toListRec[A](tree: Tree[A]): List[A] = {
#tailrec
def iter(result: List[A], todo: List[Tree[A]]): List[A] = todo match {
case x :: tail => x match {
case Node(v, l, r) => iter(v :: result, l :: r :: tail)
case EmptyTree => iter(result, tail)
}
case Nil => result.reverse
}
iter(List.empty, List(tree))
}
Without tail recursion, a(/the) stack is used to keep track of calling functions. If you want to use tail recursion, you'll have to find a way to keep track of this information elsewhere. In simpler "linear" cases, such as factorial, this information is pretty limited and can often easily be taken care of by using an accumulator.
In your case, the problem is that the recursion isn't linear. After one recursive call, the function doesn't just compute the result, but it makes another recursive call before being able to get to the result.
In order to apply tail recursion in this case, you will have to explicitly keep track of the remaining recursive calls that have to be made. An easy way is to simply keep a "to-do" list. For example:
def toList[A](t: Tree[A]): List[A] = {
#tailrec def iter[A](todo: List[Tree[A]], r: List[A]): List[A] =
todo match {
case t :: rest => t match {
case Node(v, l, r) => iter(l :: r :: rest, v :: r)
case EmptyTree => iter(rest, r)
}
case List.empty => reverse(r)
}
iter(List(t), List.empty)
}
Disclaimer: I know nothing about scala. :)
The solution that mweerden suggests would work, however, there is another way of solving the problem, which I think is much more elegant. Here is the code which traverses a tree to list
def toList[T](t: Tree[T]): List[T] = {
def tailRecursive(tree: Tree[T], acc: List[T]): List[T] = tree match {
case EmptyTree => acc
case Node(value, right, left) =>
tailRecursive(left, value :: tailRecursive(right, acc))
}
tailRecursive(t, List())
}
The solution implies that the tree is a binary search tree, and the list produced will be in ascending order (if the ascending order is not required, 6th line can be changed, putting the value in front of first recursive call or straightly into the accumulator would be possible).