foldLeft, foldRight difference on List Accumulator using Scala - scala

This
Seq(2,5,-7,4).foldLeft(0)( (acc, a) =>
if (a > 0) acc + a else acc )
gives 11
This
Seq(2,5,-7,4).foldRight(0)( (acc, a) =>
if (a > 0) acc + a else acc )
gives 7
I am surprised why, as a straight aggregation has no such issue. I.e. the results are the same. For the above 11 seems correct to me.
Reason - some Scala implementation?

a and acc need to be reversed for foldRight. Checked with a few people, no one guessed or knew that. Hence the answer.
Seq(2,5,-7,4).foldRight(0)( (a, acc) =>
if (a > 0) acc + a else acc )
Thanks to #LMMS.

Related

Proof the concatenation of ordered list is an ordered list in Stainless

I have the following code for sorting arrays which I want to verify in Stainless (previously known as Leon):
import stainless.lang._
import stainless.collection._
object QuickSort {
def isSorted(list: List[BigInt]): Boolean = list match {
case Cons(x, xs # Cons(y, _)) => x <= y && isSorted(xs)
case _ => true
}
def quickSort(list: List[BigInt]): List[BigInt] = (list match {
case Nil() => Nil[BigInt]()
case Cons(x, xs) => par(x, Nil(), Nil(), xs)
}) ensuring { res => isSorted(res) }
def par(x: BigInt, l: List[BigInt], r: List[BigInt], ls: List[BigInt]): List[BigInt] = {
require(l.forall(_ <= x) && r.forall(_ >= x))
ls match {
case Nil() => quickSort(l) ++ Cons(x, quickSort(r))
case Cons(x2, xs2) => if (x2 <= x) par(x, Cons(x2, l), r, xs2) else par(x, l, Cons(x2, r), xs2)
}
} ensuring {res => isSorted(res)}
}
I have plenty of directions to go from here (as it doesn't succeed to verify) however it seems to me that the verification should succeed with the hints provided and I want to know why it doesn't. I explain myself:
Apparently for verifying par function I need to proof that the two cases imply the isSorted postcondition separately. Now as the second case contains a recursive call then is evident that it implies the postcondition. For the first case of par, we have that the left and right subarrays are sorted and the precondition tells me that all the elements are sorted with respect to the pivot.
This last bit should imply in my opinion that the concatenating list is sorted as well. So why does it not verify? How could instruct Stainless to verify it? Do I need to add hints on the length and size to facilitate the task to Stainless?
Edit:
def concatIsSorted(l1 : List[BigInt],l2 : List[BigInt],pivot : BigInt) : Boolean = {
require(isSorted(l1) && isSorted(l2) && l1.forall(_ <= pivot) && l2.forall(_ >= pivot))
isSorted(l1 ++ Cons(pivot,l2)) because{
l1 match{
case Nil() => isSorted(Cons(pivot,l2))
case Cons(h,Nil()) => h <= pivot && isSorted(Cons(pivot,l2))
case Cons(h,t) => h <= t.head && concatIsSorted(t,l2,pivot)
}
}
}.holds
Since this is looks like a homework question, I will try to guide you towards the solution without giving it away.
First note that the program verifies if you replace the Nil() case in par with case Nil() => Nil(). This shows that the verifier is not able to prove that the result of quickSort(l) ++ Cons(x, quickSort(r)) is sorted (but it manage to do it for Nil()!).
When --debug=verification is not sufficient to understand why the verifier is not able to prove you think it should, the way to proceed is to introduce extra functions where you can precisely state your expectations. For instance if you define:
def plusplus(l: List[BigInt], r: List[BigInt]): List[BigInt] = l ++ r
And annotate it with your what you expect the verifier to prove, that is
Assuming l and r sorted and l < r (for the appropriate definition of <)
The result of l ++ r is sorted
You will see that the verifier is not able to prove this property, meaning you need to guide the verification further with addition addition auxiliary functions, pre and postcondition.
Note that this example is taken from Dependent Types for Program Termination Verification, reading the paper might help you here.

scala parallel collections not consistent

I am getting inconsistent answers from the following code which I find odd.
import scala.math.pow
val p = 2
val a = Array(1,2,3)
println(a.par
.aggregate("0")((x, y) => s"$y pow $p; ", (x, y) => x + y))
for (i <- 1 to 100) {
println(a.par
.aggregate(0.0)((x, y) => pow(y, p), (x, y) => x + y) == 14)
}
a.map(x => pow(x,p)).sum
In the code the a.par ... computes 14 or 10. Can anyone provide an explanation for why it is computing inconsistently?
In your "seqop" function, that is the first function you pass to aggregate, you define the logic that is used to combine elements within the same partition. Your function looks like this:
(x, y) => pow(y, p)
The problem is that you don't accumulate the results of a partition. Instead, you throw away your accumulator x. Every time you get 10 as a result, the calculation 2^2 was dropped.
If you change your function to take the accumulated value into account, you will get 14 every time:
(x, y) => x + pow(y, p)
The correct way to use aggregate is
a.par.aggregate(0.0)(
(acc, value) => acc + pow(value, 2), (acc1, acc2) => acc1 + acc2
)
By using (x,y) => pow(y,2) , you did not accumulate the item to the accumulator but just replaced the accumulator by pow(y,2).

Accessing the Accumulator & Element in `foldl`

In Scala's foldLeft, I know how to access the accumulator and element values in Scala, but not Haskell.
I could use foldLeft to find out, between 1 and 100, how many numbers have a remainder of 1 when divided by 3:
scala> List.range(1, 101).foldLeft(0){ (acc, elem) =>
| if (elem % 3 == 1) acc + 1
| else acc
| }
res2: Int = 33
How can I do the same in Haskell?
There's essentially a 1-to-1 correspondence:
mySum :: [Int] -> Int
mySum xs = foldl (\acc elem ->
if elem `mod` 3 == 1
then acc + 1
else acc
) 0 xs
Other than syntax and order of arguments, there's no real difference.
For future readers, it is recommended to avoid using foldl in practice. Due to laziness in foldl's implementation, space leaks can occur for large lists. Instead, there is a strict version foldl' which can be used as a drop-in replacement or the right fold foldr which has a bit format:
mySum xs = foldr (\elem acc -> -- order of arguments swapped
if elem `mod` 3 == 1
then acc + 1
else acc
) 0 xs
This is a direct translation of your Scala code to Haskell:
foldl (\acc x -> if x `mod` 3 == 1 then acc + 1 else acc) 0 [1..100]
In Haskell, because of laziness of it, using foldl usually is not a good idea, a better choose is foldl' or foldr, here is the foldr version:
foldr (\x acc -> if x `mod` 3 == 1 then acc + 1 else acc) 0 [1..100]
It's rather similar:
foldl (\acc x -> if (x `mod` 3 == 1) then acc + 1 else acc) 0 [1..100]
The first argument to foldl is the lambda, the second is the accumulator 0 and the third is the range of values.
Refer to this question to understand the differences between foldl, foldl' and foldr.

Replace if-else with functional code

I know that in functional style all if-else blocks replaced by pattern matching. But how I can handle Maps with pattern matching in Scala? For example how I can rewrite this code in more functional style?
val myMap= getMap()
if(myMap.contains(x) && myMap.contains(y)) Some(myMap(x) + myMap(y))
else if(myMap.contains(x + y)){
val z = myMap(x + y)
if (z % 2 == 0) Some(z)
else None
}
else None
Using if-else is totally acceptable for functional programming, because if-else in Scala is merely an expression. The reasons to decide between if-else and pattern-matching should be focused on improving readability, mainly.
Here's my try at rewriting your code. I'm actually not using pattern matching here, but a for-comprehension to sum the values.
def sumOfValues = for{
mx <- myMap.get(x)
my <- myMap.get(y)
} yield mx + my
def valueOfSumIfEven = myMap.get(x+y).filter(_ % 2 == 0)
sumOfValues orElse valueOfSumIfEven
To answer your question directly - you can filter the cases with an additional if:
getMap match {
case myMap if (myMap.contains(x) && myMap.contains(y)) =>
Some(myMap(x) + myMap(y))
case myMap if (myMap.contains(x+y)) =>
myMap(x+y) match {
case z if (z % 2 == 0) => Some(z)
case _ => None
}
case _ => None
}
([edit: there actually is] Although there is are "else-if's" in Scala, ) this is actually a way of doing if-else-if-else (looking at the produced class-files this is what it actually does whereas if-else is equivalent to the ternary ?: in java, returning Unit implicitly when the final else is missing).
How about:
myMap.get(x)
.zip(myMap.get(y))
.headOption.map(x => x._1 + x._2)
.orElse(myMap.get(x + y)
.filter(__ % 2 == 0))
Well, you could write your test as follows:
myMap.get(x).flatMap(xVal => myMap.get(y).map(_ + xVal))
.orElse(myMap.get(x+y).filter(_ % 2 == 0))
But what you have already may just be clearer to anyone trying to understand the intent. Note that the first line (from flatMap to the end) can also be written as a for-comprehension, as shown in #ziggystar's answer).
Maybe the modulo test part could be rewritten as a match, if that feels cleaner:
if(myMap.contains(x) && myMap.contains(y))
Some(myMap(x) + myMap(y))
else myMap.get(x + y) match {
case Some(z) if (z % 2 == 0) => Some(z)
case _ => None
}

Stable identifier required during pattern matching? (Scala)

Trying to produce a list of tuples showing prime factor multiplicity... the idea is to match each integer in a sorted list against the first value in a tuple, using the second value to count. Could probably do it more easily with takeWhile, but meh. Unfortunately my solution won't compile:
def primeFactorMultiplicity (primeFactors: List[Int]) = {
primeFactors.foldRight (List[(Int, Int)]()) ((a, b) => (a, b) match {
case (_, Nil) => (a, 1) :: b
case (b.head._1, _) => (a, b.head._2 + 1) :: b.tail
case _ => (a, 1) :: b
})
}
It says "error: stable identifier required, but b.head._1 found." But changing the second case line to the following works fine:
case (i, _) if (i == b.head._1) => (a, b.head._2 + 1) :: b.tail
Why is this, and why can't the compiler cope if there is such a simple fix?
A variable in a pattern captures the value in that position; it does not do a comparison. If the syntax worked at all, the result would be to put the value of a into b.head._1, overwriting the current value. The purpose of this is to let you use a pattern to pull something out of a complex structure.
b.head._1 is not a valid name for the result of the (x, y) tuple extractor
Try this instead:
case (x, _) if x == b.head._1 => (a, b.head._2 + 1) :: b.tail