How recursion in scala tree((sealed trait) - scala

when I programming task in scala I crashed the problem
the error code is missing parameter type for expanded function.
Expected type was: Int
def sum_tree(t : Tree[Int]): int ={
sealed trait Tree[Int]
case class Leaf[Int](elem: Int) extends Tree[Int]
case class Node[Int](elem: Int, left: Tree[Int], right: Tree[Int]) extends Tree[Int]
val tree = Node(7, Node(3, Leaf(1), Leaf(2)), Leaf(4))
def sum_tree(t : Tree[Int]): Int = {
//must use recursion call function.
case Leaf(elem) => elem
case Node(elem, l, r) => elem + sum_tree(l) + sum_tree( l )
case None => 0
}
println("** p6 **")
println(sum_tree(tree)

Your pattern matching is missing match to be a valid match expression. Also note that t is Tree and there is None declared which implements it so last case clause is invalid; and you were calling sum_tree(l) twice when the second one should be sum_tree(r)
def sum_tree(t: Tree[Int]): Int = t match
case Leaf(elem) => elem
case Node(elem, l, r) => elem + sum_tree(l) + sum_tree(r)

Related

Expression based on class of an object in Scala

I am trying to write an expression based on the class of an object.
case class Fork(left: CodeTree, right: CodeTree, chars: List[Char], weight: Int) extends CodeTree
case class Leaf(char: Char, weight: Int) extends CodeTree
val l1 = new Leaf('A', 1)
val l2 = new Leaf('B', 1)
val f1 = new Fork(l1, l2, List(l1.char, l2.char), l1.weight + l2.weight)
I have tried two methods, but those of them have issues.
Method 1:
val w: Int = f1 match {
case Fork(_, _, _, w) => println("I am a fork")
case Leaf(_, w) => println("I am a Leaf")
}
Error received:
Error:(15, 8) constructor cannot be instantiated to expected type;
found : Leaf
required: Fork
case Leaf(_, w) => {w}
Method 2:
if (l1.isInstanceOf[Fork]) println("I am a fork") else println("I am a leaf")
Warning received:
Warning:(10, 20) fruitless type test: a value of type Leaf cannot also be a Fork
if (l1.isInstanceOf[Fork]) println("I am a fork") else println("I am a leaf")
It is just a warning because the compiler knows that f1 is always fork and is telling you, that you are basically doing if (true)
Code that would work for you is:
val f1: CodeTree = new Fork(l1, l2, List(l1.char, l2.char), l1.weight + l2.weight)
val w = f1 match {
case f: Fork => println("I am a fork")
case l: Leaf => println("I am a Leaf")
}
I have annotated the f1 to CodeTree type
I have removed the annotation of w
then you can modify to whatever:
val w = f1 match {
case f: Fork => f.weight
case l: Leaf => l.weight
}

Scala generics: type mismatch with folding

New to scala. Trying to understand why scala compiler is not happy about the below:
sealed trait LinkedList[A] {
def fold[B](end: B)(func: (A, B) => B): B =
this match {
case End() => end
case Pair(hd, tl) => func(hd, tl.fold(end)(func))
}
def sum: Int =
fold[Int](0){(hd, tl) => hd + tl}
}
final case class Pair[A](head: A, tail: LinkedList[A]) extends LinkedList[A]
final case class End[A]() extends LinkedList[A]
object Foo extends App {
val example = Pair(1, Pair(2, Pair(3, End())))
println(example.sum)
}
Getting this error:
Error:(10, 35) type mismatch;
found : Int
required: String
fold[Int](0){(hd, tl) => hd + tl}
How is String being inferred here?
Please help.
For a general A, usual "addition" is not defined. So instead, it implicitly converts A into String, and uses the + that concatenates Strings. A quick and dirty workaround would be:
def sum(implicit i: A =:= Int): Int = fold[Int](0){(hd, tl) => i(hd) + tl}
This would make sum available only if A is Int. A somewhat more systematic approach would be to use Numeric typeclass, just like the method in the standard library (unfold "use case" and "Full signature").

How does Scala deal with recursive return types?

In OCaml there's this thing called 'rectype' which allows recursive return-types. To illustrate what I mean by that here's a method with such a type:
def foo(n: Int)(i: Int): ??? = {
val m = n + i
(foo(m), m)
}
The question is; what do you put in ???'s place? Looking at the code you'd think it's something like:
Int => Int => (Int => (Int => (Int => (Int => ... , Int)
Why? Because the type of foo(m) is Int => (Int => rep, Int) where rep in the tuple is the repeated structure.
Is there a way to do this?
Sure, Scala has recursive types (but perhaps not the kind you're looking for). Take List, for example (abridged to relevant parts):
sealed abstract class List[+A] ...
final case class ::[B](head: B, tl: List[B]) extends List[B] ...
object Nil extends List[Nothing] ...
List(1, 2, 3) is recursively defined from multiple lists using cons ::.
1 :: 2 :: 3 :: Nil
Or without infix notation:
::(1, ::(2, ::(3, Nil)))
I suppose you could represent the type this way. But notice you have to define the type yourself:
sealed abstract class Inf[A]
case class Func[A](_1: A => Inf[A], _2: A) extends Inf[A] with Product2[A => Inf[A], A]
object Identity extends Inf[Nothing]
def foo(n: Int)(i: Int): Inf[Int] = {
val m = n + i
Func(foo(m) _, m)
}
Or a little more specifically:
def foo(n: Int)(i: Int): Func[Int] = {
val m = n + i
Func(foo(m) _, m)
}
scala> val f = foo(5)(3)
f: Func[Int] = Func(<function1>,8)
scala> f._1(10)
res8: Inf[Int] = Func(<function1>,18)
In your particular case, the return type would depend on the two input values n and i. Both of these are unknown at compile time (Scala is statically typed!), which means the compiler wouldn't know the static return type. This is obviously bad for numerous reasons.
In general, you can neither define recursive types, nor can you utilize type inference for recursive methods.

I want my function to return a Stream[T], but I can't figure out how to make it type check

I'm playing with some basic programming exercises in order to learn Scala better, but I'm stuck on trying to figure out why my code won't type check.
The sticking point is the possibilities function. I want a function which returns a stream containing all possible arrangements of numbers and math operators given a list of numbers.
I'm confused because changing the return type of the function to read Stream[Object] type-checks just fine and returns results that appear to be Streams of Equations. However, the version included below does not type check with the return type of possibilites set to Stream[Equation].
As a side note, I understand that appending opsMix with cards doesn't put the Operations in the correct order, but I'd like to solve this part of the problem first. I think I'll use flatMap or zipAll with flatten to accomplish that part.
Also - this is not a homework assignment!
abstract class Operation
case class Add() extends Operation
case class Subtract() extends Operation
case class Multiply() extends Operation
case class Divide() extends Operation
case class Num(val valu: Float) extends Operation
type Equation = List[Operation]
def calc(equa: Equation): Float =
equa match {
case Num(x) :: List() => x
case Num(x) :: y :: Num(z) :: xs => y match {
case Add() => calc( Num(x + z)::xs )
case Subtract() => calc( Num(x - z)::xs )
case Multiply() => calc( Num(x * z)::xs )
case Divide() => calc( Num(x / z)::xs )
}
case _ => 0
}
// from http://stackoverflow.com/questions/1070859/listing-combinations-with-repetitions-in-scala
def mycomb[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l;
sl <- mycomb(n-1, l dropWhile { _ != el } ))
yield el :: sl
}
def comb[T](n: Int, l: List[T]): List[List[T]] = mycomb(n, l.removeDuplicates)
val ops = List(Add, Subtract, Multiply, Divide)
def possibilities(cards: List[Num]) : Stream[Equation] =
{ for {
hand <- cards.permutations
opMix <- comb(cards.length-1, ops)
} yield hand ++ opMix
}.toStream
// test value:
val ppp = possibilities(List(Num(20), Num(3), Num(7), Num(100)))
The problem is that you declared your operation case classes as Add() etc., but in val ops you use just List(Add, ...). If you try declaring ops with the correct type:
val ops: List[Operation] = List(Add, Subtract, Multiply, Divide)
you'll see the errors. (This is why it's often helpful to add types yourself instead of relying on the type checker - it helps to find errors.)
I suggest you to update your class hierarchy to use case object for singleton operations:
abstract class Operation
case object Add extends Operation
case object Subtract extends Operation
case object Multiply extends Operation
case object Divide extends Operation
case class Num(val valu: Float) extends Operation
Of course you'll need to update your patterns as well:
def calc(equa: Equation): Float =
equa match {
case Num(x) :: List() => x
case Num(x) :: y :: Num(z) :: xs => y match {
case Add => calc( Num(x + z)::xs )
case Subtract => calc( Num(x - z)::xs )
case Multiply => calc( Num(x * z)::xs )
case Divide => calc( Num(x / z)::xs )
}
case _ => 0
}
Then possibilities works as expected without any changes.
Alternatively, you can keep the classes the way you have them, just change ops to
val ops: List[Operation] =
List(Add(), Subtract(), Multiply(), Divide())
Update:
Concerning interleaving, you could do something like:
def interleave[T](xs: List[T], ys: List[T], padX: T, padY: T): List[T] =
xs.zipAll(ys, padX, padY).flatMap(pair => List(pair._1, pair._2))
but note the result will always have an even number of elements. Perhaps a better solution would be to implement interleave yourself, something like:
def interleave[T](xs: List[T], ys: List[T]): List[T] = {
import collection.mutable._;
#annotation.tailrec
def f(xs: List[T], ys: List[T], r: Buffer[T]): Buffer[T] =
xs match {
// By swapping the arguments, we get interelaving:
case x :: xrest => f(ys, xrest, r += x);
case Nil => r ++= ys;
}
return f(xs, ys, new ArrayBuffer[T]).toList;
}
However, I'd say that even better solution would be not to mix operations and numbers. Instead, you could declare a special class for well-formed expression formed from your symbols, something like (untested):
sealed abstract class Symbol
sealed abstract class Operation extends Symbol
case object Add Operation
case object Subtract extends Operation
case object Multiply extends Operation
case object Divide extends Operation
case class Num(val valu: Float) extends Symbol
sealed abstract class Expression;
case class App(val op: Operation, val arg1: Expression, val arg2: Expression)
extends Expression;
case class Const(val n: Num)
extends Expression;
and instead of creating an interleaved list, create an instance of Expression.

implicit parameter definition in class

implicit val odkaz = head;
def vypis(implicit odkaz:Prvek):String = {
odkaz match{
case null => ""
case e => e.cislo + " " + e.pocet + "\n" + vypis(e.dalsi)
}
}
...
def main(args:Array[String]){
val q = new MyQueue() // insert some values
println(q.vypis)
}
This method(vypis) is a member of an queue-class so I'll always want to implicity start the recursion from the start of the queue, when calling the method from outside. Is there a way how to write it, that the method from outside calling, there's no paramter, but in inside, there's a parameter - for recursion...?
The compiler complains that the parameter is not defined when called from outside
Or is there are way how can specify the default value for a method's parameter?
Using a nested method
def sum(list: List[Int]) = {
#annotation.tailrec
def sum(ls: List[Int], s: Int): Int = ls match {
case x :: xs => sum(xs, x + s)
case _ => s
}
sum(list, 0)
}
Using a default parameter for the accumulator
#annotation.tailrec
def sum(list: List[Int], s: Int = 0): Int = list match {
case x :: xs => sum(xs, x + s)
case _ => s
}
The second approach (only possible with Scala 2.8) unneccesarily broadens the public API, so I would recommend the first.
In Scala 2.8, default method (and constructor) parameters are available:
def m1(i: Int = 23): Int = i * 2