I want to remove all instances of an element from a list, like this:
def remove(x: Char, xs: List[Char]) = xs match {
case Nil => Nil
case x :: ys => remove(x, ys)
case y :: ys => y :: remove(x, ys)
}
However, I get an error on the line case y :: ys => y :: remove(x, ys) saying Cannot resolve symbol ::
Am I pattern matching correctly?
I got a couple of different compile errors, first: "error: recursive method remove needs result type" (fixed by adding return type of List[Char]), then (as I expected): "warning: unreachable code" on the line with y :: ys. This latter warning comes because the x used in the line with case x :: ys is not recognised as the same x from the function's arguments - it is shadowing the argument variable, and so matched any character.
To be sure to match the function argument, add backticks:
def remove(x: Char, xs: List[Char]): List[Char] = xs match {
case Nil => Nil
case `x` :: ys => remove(x, ys)
case y :: ys => y :: remove(x, ys)
}
or you can capitalise the argument name (capitalised variables in a match case are treated specially this way):
def remove(X: Char, xs: List[Char]): List[Char] = xs match {
case Nil => Nil
case X :: ys => remove(X, ys)
case y :: ys => y :: remove(X, ys)
}
If using this style, don't forget to capitalise the argument everywhere it is referenced!
You need to specify the return type if you are using recursive call. This will work:
def remove(x: Char, xs: List[Char]):List[Char] = xs match {
case Nil => Nil
case x :: ys => remove(x, ys)
case y :: ys => y :: remove(x, ys)
}
I agree, the error is misleading
The first problem is that a recursive method needs to declare its return type.
def remove(x: Char, xs: List[Char]): List[Char] = xs match {
case Nil => Nil
case x :: ys => remove(x, ys)
case y :: ys => y :: remove(x, ys)
}
The second problem is that both cases are the same so the second one is unreachable.
Related
How can I print the element of List after each iteration?
scala> def carry(c: Int, list: List[Int]):List[Int] = (c, list) match {
|
| case (0, xs) => xs
|
| case (1, Nil) => List(1)
|
| case (1, x :: xs) => println(x,xs)((1 - x) :: carry(x, xs))
|
| case (_, _) => throw new IllegalArgumentException("Invalid input!!!")
| }
<console>:18: error: Unit does not take parameters
case (1, x :: xs) => println(x,xs)((1 - x) :: carry(x, xs))
your call to println(x, xs) returns a Unit type, and you're trying to call the return value with argument (1 - x) :: carry(x, xs). Perhaps you already knew that. Curly braces are your friend here, as they create a contained expression. Here's the solution:
case (1, x :: xs) => {println(x, xs); (1 - x) :: carry(x, xs)}
or
case (1, x :: xs) => {
println(x, xs)
(1 - x) :: carry(x, xs)
}
I have been trying to learn pattern matching and pairs in Scala and use it to implement the merge sort but the pattern matching. But the pattern match to extract head and tail pair doesn't work. What is it which I am missing in the below code?
def merge(xs: List[Int], ys: List[Int]): List[Int] =
(xs, ys) match {
case (x: Int, y: Int) :: (xs1: List[Int], ys1: List[Int]) =>
if (x < y) x :: merge(xs1, ys)
else y :: merge(xs, ys1)
case (x: List[Int], Nil) => x
case (Nil, y: List[Int]) => y
}
you have a syntax error in your 1st case statement, change it to
case (x :: xs1 , y :: ys1)
from
case (x: Int, y: Int) :: (xs1: List[Int], ys1: List[Int])
You are trying to match a tuple containing Lists, not List of Tuples
I am following the Functional Programming in Scala lecture on Coursera and at the end of the video 5.7, Martin Odersky asks to prove by induction the correctness of the following equation :
(xs ++ ys) map f = (xs map f) ++ (ys map f)
How to handle proof by induction when there are multiple lists involved ?
I have checked the base cases of xs being Nil and ys being Nil.
I have proven by induction that the equation holds when xs is replaced by x::xs, but do we also need to check the equation with ys replaced by y::ys ?
And in that case (without spoiling the exercise too much...which is not graded anyway) how do you handle : (xs ++ (y::ys)) map f ?
This is the approach I have used on a similar example, to prove that
(xs ++ ys).reverse = ys.reverse ++ xs.reverse
Proof (omitting the base case, and easy x::xs case) :
(xs ++ (y::ys)).reverse
= (xs ++ (List(y) ++ ys)).reverse //y::ys = List(y) ++ ys
= ((xs ++ List(y)) ++ ys).reverse //concat associativity
= ys.reverse ++ (xs ++ List(y)).reverse //by induction hypothesis (proven with x::xs)
= ys.reverse ++ List(y).reverse ++ xs.reverse //by induction hypothesis
= ys.reverse ++ (y::Nil).reverse ++ xs.reverse //List(y) = y :: Nil
= ys.reverse ++ Nil.reverse ++ List(y) ++ xs.reverse //reverse definition
= (ys.reverse ++ List(y)) ++ xs.reverse //reverse on Nil (base case)
= (y :: ys).reverse ++ xs.reverse //reverse definition
Is this right ?
The property involves multiple lists, but ++ only recurses on its left argument. That's a hint that you can prove by induction on that left argument. In general, when proving a proposition about some recursive function, the first thing you try is inducting on the same argument that function recurses on.
I'll do this one for you as an example:
Claim: (xs ++ ys) map f = (xs map f) ++ (ys map f)
Proof: by induction on xs.
Base case: xs = Nil
lhs = (Nil ++ ys) map f = ys map f
(by ++'s definition)
rhs = (Nil map f) ++ (ys map f) = Nil ++ ys map f = ys map f
(by map's, then ++'s definitions)
Hence lhs = rhs
Inductive case: xs = z :: zs
hypothesis: (zs ++ ys) map f = (zs map f) ++ (ys map f)
goal: ((z :: zs) ++ ys) map f = ((z :: zs) map f) ++ (ys map f)
lhs = (z :: (zs ++ ys)) map f = f(z) :: ((zs ++ ys) map f) (1)
(by map's definition)
rhs = ((z :: zs) map f) ++ (ys map f) = (f(z) :: (zs map f)) ++ (ys map f)
(by map's definition)
in turn, rhs = f(z) :: ((zs map f) ++ (ys map f)) (2)
(by ++'s definition)
From hypothesis, (1) and (2), we have proven goal.
Therefore, we have proven the claim to be true reguardless of xs, ys, and f.
As the comment of #Phil says, first is a good understaning of what the methods ++ and :: are doing on the lists the better way is the documentation
How can we prove properties of list programs?
The answer is by Structural induction!
Proof rule for proving a list property P(xs) via structural induction:
P(Nil) (base case)
for all x,xs : P(xs) => P(x::xs) (induction step)
for all xs : P(xs) (consequence)
P(xs) in induction step is called induction hypothesis
for as the only important thing is xs, ys is fix proper List with lenght l, after proving for xs you can proof for ys, or see that is commutative
So let's apply induction and the definitions of the functions
P(xs): (xs ++ ys) map f = (xs map f) ++ (ys map f)
Base case we substitue xs by nil
(nil ++ ys) map f [definition of ++ ]
ys map f on the other hand
(xs map f) ++ (ys map p) [apply map over NIL]
(NIL) ++ (ys map p) [definition pf ++]
ys map p
Induction Step
((x::xs) ++ ys) map f [definition ++]
(x:: (xs ++ ys)) map f [definition map]
f(x) :: ((xs ++ ys) map f) [induction hypothesis]
f(x) :: ((xs map f) ++ (ys map f)) [definition ++]
(f(x) :: (xs map f)) ++ (ys map f) [definition map]
(x::xs) map f ++ ys map f
q.e.d
for example another case in a scala work sheet
import scala.util.Random
// P : length ( append(as,bs) )) = length ( as ) + length (bs)
def length[T](as: List[T]): Int = as match {
case Nil => 0
case _::xs => 1 + length(xs)
}
def append[T](as: List[T], bs: List[T]): List[T] = as match {
case Nil => bs
case x :: xs => x :: append(xs, bs)
}
// base case we substitute Nil for as in P
val a:List[Int] = Nil
val n = 10
val b:List[Int] = Seq.fill(n)(Random.nextInt).toList
length((append(a,b)))
length(a)
length(b)
import scala.util.Random
length: length[T](val as: List[T]) => Int
append: append[T](val as: List[T],val bs: List[T]) => List[T]
a: List[Int] = List()
n: Int = 10
b: List[Int] = List(1168053950, 922397949, -1884264936, 869558369, -165728826, -1052466354, -1696038881, 246666877, 1673332480, -975585734)
res0: Int = 10
res1: Int = 0
res2: Int = 10
here you can find more examples
I have an assignment to translate the following ML code into Java, but I cannot tell what it is doing. What are the 'halve' and 'merge' functions doing here?
fun halve nil = (nil, nil)
| halve [a] = ([a], nil)
| halve (a :: b :: cs) =
let
val (x, y) = halve cs
in
(a :: x, b :: y)
end;
fun merge (nil, ys) = ys
| merge (xs, nil) = xs
| merge (x :: xs, y :: ys) =
if (x > y) then x :: merge(xs, y :: ys)
else y :: merge(x :: xs, ys);
fun mergeSort nil = nil
| mergeSort [a] = [a]
| mergeSort theList =
let
val (x, y) = halve theList
in
print("xList: "^printList(x));
print("yList: "^printList(y));
merge(mergeSort x, mergeSort y)
end;
halve splits a list in two by adding its elements alternatingly to two lists (this saves you from having to calculate the length first and then splitting it, which would require 1.5 traversals of the list instead of just one).
merge merges two lists in decreasing order.
mergeSort splits a list in two, sorts the two halves, then merges the sorted sublists.
Here is a function I wrote for concatenating elements of a List using an accumulator with tail recursion :
val l1 = List(1, 2, 3) //> l1 : List[Int] = List(1, 2, 3)
val l2 = List(1, 2, 3) //> l2 : List[Int] = List(1, 2, 3)
def func(l1: List[Int], l2: List[Int], acc: List[Int]): List[Int] = {
(l1, l2) match {
case (Nil, Nil) => acc.reverse
case (h1 :: t1, h2 :: t2) => {
func(t1, t2, h1 :: h2 :: acc)
}
}
} //> func: (l1: List[Int], l2: List[Int], acc: List[Int])List[Int]
func(l1, l2, List()) //> res0: List[Int] = List(1, 1, 2, 2, 3, 3)
This is my understanding of the call order
func( 1 :: 1 :: () )
func( 2 :: 2 :: 1 :: 1 : () )
func( 3 :: 3 :: 2 :: 2 :: 1 :: 1 : () )
So the call order is the reason why I must call reverse on base call of acc so that the List is ordered in same ordering initial List elements. To try to minimize the steps required to concatenate the lists I have tried to add the elements like this :
func(t1, t2, acc :: h1 :: h2)
instead of
func(t1, t2, h1 :: h2 :: acc)
but receive compile time error :
value :: is not a member of Int
So it seems I cannot prepend these elements to this List ?
When you write x :: y, y must be a list and x the element you want to prepend.
You can use acc :+ h1 :+ h2 to append h1 and h2 to acc, but note that adding elements to the end of the list is a relatively expensive operation (linear with the length of the list).