Difficulty understanding this type signature - scala

merge sort type signature :
def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T] = {
The function is called using :
msort[Int]((a, b) => a < b) _
Does the type msort[Int] type the parameters a & b to Int ?
To better understand this type signature I've tried to extract the less function :
def lessFunc[Int]((a , b) : (Int , Int)) : Boolean = {
true
}
But this is not correct ?
Entire code :
def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T] = {
def merge(xs: List[T], ys: List[T], acc: List[T]): List[T] =
(xs, ys) match {
case (Nil, _) => ys.reverse ::: acc
case (_, Nil) => xs.reverse ::: acc
case (x :: xs1, y :: ys1) =>
if (less(x, y)) merge(xs1, ys, x :: acc)
else merge(xs, ys1, y :: acc)
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(less)(ys), msort(less)(zs), Nil).reverse
}
}

This is a function which takes two lists of parameters. The first list contains a less function, which as you've guessed correctly when invoked with [Int] is typing the parameters to Int.
You have just expanded it wrong. What you should have done is
def less(a: Int, b: Int) = true
or to match your anonymous function
def less(a: Int, b: Int) = a < b
Now when you call your msort like msort[Int](less) _ (see currying) you'll get a new function which is able to sort Lits[Int].
val listSorter = msort[Int](less) _
listSorter(List(1, 2, 3))

def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T]
is a function with two parameter lists that returns List of type T. First parentheses let you pass a function that will be used for sorting the list.
(T,T) => Boolean - means that the function will take two parameters and yield boolean.
The second parentheses take a List of type T . This T after name of the function is like generics in Java. You use it to pass a type. It can be called like:
def msort[String]((a,b) => a.length < b.length)(some list) if you want to sort List of String's by their length. Or you can call it like in the example to sort List of Ints
def msort[Int]((a,b) => a < b)(some list)
Because function is defined with two sets of parameters we can take advantage of it by applying only part of them and build specialised functions based on that one. Like for example:
val stringSort = msort[String]((a,b) => a.length < b.length) _
val ascendingIntSort = msort[Int]((a,b) => a < b) _
These are curried functions because stringSort's signature is List[Strint] => List[String]. Now you can reuse these methods by passing only instances of Lists to them:
stringSort(List("cat", "elephant", "butterfly"))
ascendingIntSort(List(4,1,3,2))

Related

Filter from Seq less/greater elements and only one equal

I want to implement method in Scala which filters from Seq elements which are for example greater than provided value and additionally returns up to one equal element. For example:
greaterOrEqual(Seq(1,2,3,3,4), 3) shouldBe Seq(3,4)
I ended up with such method:
def greaterOrEqual(
seq: ArrayBuffer[Long],
value: Long
): ArrayBuffer[Long] = {
val greater = seq.filter(_ > value)
val equal = seq.filter(_ == value)
if (equal.isEmpty) {
greater
} else {
equal.tail ++ greater
}
}
but somehow it doesn't look nice to me :) Moreover, I'd like to have generic version of this method where I'd able to use not only Long type but custom case classes.
Do you have any suggestions?
Thanks in advance.
def foo[A : Ordering[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(implicitly[Ordering[A]].gt(_,value))
Or (different style)
def foo[A](seq: Seq[A], value: A)(implicit ord: Ordering[A]) = {
import ord._
seq.find(_ == value).toList ++ seq.filter(_ > value)
}
The code below is deprecated
scala> def foo[A <% Ordered[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(_ > value)
foo: [A](seq: Seq[A], value: A)(implicit evidence$1: A => Ordered[A])List[A]
scala> foo(Seq(1,2,3,3,4,4,5),3)
res8: List[Int] = List(3, 4, 4, 5)
Here's my take on it (preserving original order).
import scala.collection.mutable.ArrayBuffer
def greaterOrEqual[A]( seq :ArrayBuffer[A], value :A
)(implicit ord :Ordering[A]
) : ArrayBuffer[A] =
seq.foldLeft((ArrayBuffer.empty[A],true)){
case (acc, x) if ord.lt(x,value) => acc
case ((acc,bool), x) if ord.gt(x,value) => (acc :+ x, bool)
case ((acc,true), x) => (acc :+ x, false)
case (acc, _) => acc
}._1
testing:
greaterOrEqual(ArrayBuffer.from("xawbaxbt"), 'b')
//res0: ArrayBuffer[Char] = ArrayBuffer(x, w, b, x, t)
This is an excellent problem for a simple tail-recursive algorithm over lists.
def greaterOrEqual[T : Ordering](elements: List[T])(value: T): List[T] = {
import Ordering.Implicits._
#annotation.tailrec
def loop(remaining: List[T], alreadyIncludedEqual: Boolean, acc: List[T]): List[T] =
remaining match {
case x :: xs =>
if (!alreadyIncludedEqual && x == value)
loop(remaining = xs, alreadyIncludedEqual = true, x :: acc)
else if (x > value)
loop(remaining = xs, alreadyIncludedEqual, x :: acc)
else
loop(remaining = xs, alreadyIncludedEqual, acc)
case Nil =>
acc.reverse
}
loop(remaining = elements, alreadyIncludedEqual = false, acc = List.empty)
}
Which you can use like this:
greaterOrEqual(List(1, 3, 2, 3, 4, 0))(3)
// val res: List[Int] = List(3, 4)
You can use the below snippet:
val list = Seq(1,2,3,3,4)
val value = 3
list.partition(_>=3)._1.toSet.toSeq
Here partition method divide the list into two list. First list which satisfy the given condition, and second list contains the remaining elements.
For generic method you can using implicit Ordering. Any type who can compare elements can be handled by greaterOrEqual method.
import scala.math.Ordering._
def greaterOrEqual[T](seq: Seq[T], value: T)(implicit ordering: Ordering[T]): Seq[T] = {
#scala.annotation.tailrec
def go(xs: List[T], value: T, acc: List[T]): List[T] = {
xs match {
case Nil => acc
case head :: rest if ordering.compare(head, value) == 0 => rest.foldLeft(head :: acc){
case (result, x) if ordering.compare(x, value) > 0 => x :: result
case (result, _) => result
}
case head :: rest if ordering.compare(head, value) > 0 => go(rest, value, head :: acc)
case _ :: rest => go(rest, value, acc)
}
}
go(seq.toList, value, List.empty[T]).reverse
}

Scala Recursively Count Elements Given Predicate

I have this iterative function which counts the number of Boolean values in a list.
def countBoolIter[A](test: A=>Boolean, a: List[A]) = {
var count = 0
for(elem <- a){
if(test(elem)) count += 1
}
count
}
The first parameter passed in is an isBool function:
def isBool(i: Any) = i match {
case _: Boolean => true
case _ => false
}
Calling the function looks like this:
countBoolIter(isBool, List(1, true, 3, true, false, "hi"))
// Output: 3
Now, I tried converting it into a tail recursive function like this:
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if(test(h)) => countBoolRec(test, a, acc+1)
case h :: t => countBoolRec(test, a, acc)
}
However, I'm getting a runtime error because the function doesn't return anything; no errors are thrown. I presume that it is stuck in an infinite loop that's why nothing is being returned.
Question: How should I fix my attempted recursive implementation?
There is an error in the function countBoolRec:
#tailrec
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if(test(h)) => countBoolRec(test, t, acc+1)
case h :: t => countBoolRec(test, t, acc)
}
In the recursive call, use t as the parameter and no again a. If not, basically, you are in an infinite loop.
Also, better to use the #tailrec annotation to be sure that the implementation is "tail recursive".
You're repeatedly recursing with the same list as input.
Consider the case where a.head passes the test:
countBoolRec(test, a, 0)
countBoolRec(test, a, 1)
countBoolRec(test, a, 2)
... and so on
#scala.annotation.tailrec // Not that your original code wasn't tail-recursive, but it's a generally good practice to mark code that isn't tail recursive with this annotation
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match {
case Nil => acc
case h :: t if (test(h)) => countBoolRec(test, t, acc + 1)
case h :: t => countBoolRec(test, t, acc)
}
Though you could also just as well write:
(0 /: a) { (acc, v) => acc + (if (test(v)) 1 else 0) }

Recursively handle nested lists in scala

I'm teaching myself scala and trying to fatten my FP skills.
One of my references, Essentials of Programming Languages (available here), has a handy list of easy recursive functions. On page page 27/50, we are asked to implement swapper() function.
(swapper s1 s2 slist) returns a list the same as slist, but
with all occurrences of s1 replaced by s2 and all occurrences of s2 replaced by s1.
> (swapper ’a ’d ’(a b c d))
(d b c a)
> (swapper ’a ’d ’(a d () c d))
(d a () c a)
> (swapper ’x ’y ’((x) y (z (x))))
((y) x (z (y)))
In scala, this is:
swapper("a", "d", List("a","b","c","d"))
swapper("a", "d", List("a","d",List(),"c","d"))
swapper("x", "y", List( List("x"), "y", List("z", List("x"))))
My scala version handles all versions save the final x.
def swapper(a: Any, b: Any, lst: List[Any]): List[Any] ={
def r(subList :List[Any], acc : List[Any]): List[Any] ={
def swap (x :Any, xs: List[Any]) =
if(x == a){
r(xs, acc :+ b)
} else if (x == b) {
r(xs, acc :+ a)
} else {
r(xs, acc :+ x)
}
subList match {
case Nil =>
acc
case List(x) :: xs =>
r(xs, r(List(x), List()) +: acc)
case x :: xs =>
swap(x,xs)
//case List(x) :: xs =>
}
}
r(lst, List())
}
Instinctively, I think this is because I have no swap on the section "case List(x) :: xs" but I'm still struggling to fix it.
More difficult, still, this case breaks the tail-call optimization. How can I do this and where can I go to learn more about the general solution?
You can use this foldRight with pattern match approach:
def swapper(a:Any, b:Any, list:List[Any]):List[Any] =
list.foldRight(List.empty[Any]) {
case (item, acc) if item==a => b::acc
case (item, acc) if item==b => a::acc
case (item:List[Any], acc) => swapper(a, b, item)::acc
case (item, acc) => item::acc
}
or even simplier (thanks to #marcospereira):
def swapper(a:Any, b:Any, list:List[Any]):List[Any] =
list.map {
case item if item==a => b
case item if item==b => a
case item:List[Any] => swapper(a, b, item)
case item => item
}
A simpler way to solve this is just use map:
def swapper[T](a: T, b: T, list: List[T]): List[T] = list.map { item =>
if (item == a) b
else if (item == b) a
else item
}
This seems to work.
def swapper[T](a: T, b: T, lst: List[_]): List[_] = {
val m = Map[T, T](a -> b, b -> a).withDefault(identity)
def swap(arg: List[_]): List[_] = arg.map{
case l: List[_] => swap(l)
case x: T => m(x)
}
swap(lst)
}
The List elements are inconsistent because it might be an element or it might be another List, so the type is List[Any], which is a sure sigh that someone needs to rethink this data representation.

How to call merge sort

The code below is based on Merge sort from "Programming Scala" causes stack overflow
def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T] = {
def merge(xs: List[T], ys: List[T], acc: List[T]): List[T] =
(xs, ys) match {
case (Nil, _) => ys.reverse ::: acc
case (_, Nil) => xs.reverse ::: acc
case (x :: xs1, y :: ys1) =>
if (less(x, y)) merge(xs1, ys, x :: acc)
else merge(xs, ys1, y :: acc)
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(less)(ys), msort(less)(zs), Nil).reverse
}
}
When I try to invoke msort using :
val l = List(5, 2, 4, 6, 1, 3)
msort[Int](l)
I receive error :
Multiple markers at this line - type mismatch; found : List[Int] required: (Int, Int) => Boolean - type mismatch;
found : List[Int] required: (Int, Int) => Boolean - missing arguments for method msort in object mergesort; follow
this method with `_' if you want to treat it as a partially applied function
How do I invoke msort & why is a function required as part of the invocation ?
In Scala it is possible to have Multiple Parameters Lists. Your invocation only passes one argument.
The method is declared as def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T], so the first argument is of type (T, T) => Boolean, which is a function taking two parameters of type T and returning a Boolean value. You pass there a List[Int], which makes Scala complain.
Why would you like to have such a thing you may ask. Well, consider following example.
val stringSorter = msort[String]((a, b) => a.compareTo(b) < 0) _
// stringSorter: List[String] => List[String] = <function1>
val integerSorter = msort[Int]((a, b) => a < b) _
// integerSorter: List[Int] => List[Int] = <function1>
Those two invocation create two new functions taking only a single parameter - the list you want to sort. You don't have to tell it how to compare the elements, because you already did. Note you can invoke the same function with different lists as an argument.
integerSorter(List(2, 3, 1))
// res0: List[Int] = List(1, 2, 3)
integerSorter(List(2, 4, 1))
// res1: List[Int] = List(1, 2, 4)
stringSorter(List("b", "a", "c"))
res3: List[String] = List(a, b, c)
Note also that the newly created functions are type safe and following code will fail:
integerSorter(List("b", "a", "c"))
<console>:10: error: type mismatch;
found : String("b")
required: Int
integerSorter(List("b", "a", "c"))
Implicit Parameters
As the article in the link mentioned one of the reasons you may want to use Multiple Parameter Lists are implicit parameters.
When using implicit parameters, and you use the implicit keyword, it
applies to the entire parameter list. Thus, if you want only some
parameters to be implicit, you must use multiple parameter lists.
Let's modify the example code you gave us a bit to introduce a new type:
trait Comparator[T] {
def less(a: T, b: T): Boolean
}
and let's swap the parameter lists, and add implicit keyword to the second one, so now it becomes:
def msort[T](xs: List[T])(implicit c: Comparator[T]): List[T] = {
def merge(xs: List[T], ys: List[T], acc: List[T]): List[T] =
(xs, ys) match {
case (Nil, _) => ys.reverse ::: acc
case (_, Nil) => xs.reverse ::: acc
case (x :: xs1, y :: ys1) =>
if (c.less(x, y)) merge(xs1, ys, x :: acc)
else merge(xs, ys1, y :: acc)
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(ys)(c), msort(zs)(c), Nil).reverse
}
}
Now you can declare implicit object which will be used in case you don't supply one, e.g.
implicit val intComparator = new Comparator[Int] { def less(a: Int, b: Int) = a < b }
msort(List(5, 3, 1, 3))
// res8: List[Int] = List(1, 3, 3, 5)
While this may not seem to be very appealing it gives you extra flexibility when designing your API. Let's assume that we have a type called CustomType. It can declare an implicit in the companion object and it will be resolved "automatically" by the compiler.
case class CustomType(ordinal: Int, name: String)
object CustomType {
implicit val customTypeComparator = new Comparator[CustomType] {
def less(a: CustomType, b: CustomType) = a.ordinal < b.ordinal
}
}
msort(List(CustomType(2, "Second"), CustomType(1, "First")))
// res11: List[CustomType] = List(CustomType(1,First), CustomType(2,Second))
def msort[T](less: (T, T) => Boolean)(xs: List[T]): List[T]
This function takes two arguments: a function less and a list xs.
How do I invoke msort?
You have to provide values for both arguments: msort(...)(...).
Why is a function required as part of the invocation?
Because the argument less is declared with function type (T, T) => Boolean.

Example in Scala of hashmap forall() method?

Can someone please give an example of how to use the HashMap forall() method? I find the Scala docs to be impenetrable.
What I want is something like this:
val myMap = HashMap[Int, Int](1 -> 10, 2 -> 20)
val areAllValuesTenTimesTheKey = myMap.forall((k, v) => k * 10 == v)
but this gives:
error: wrong number of parameters; expected = 1
You need instead
val myMap = HashMap[Int, Int](1 -> 10, 2 -> 20)
val areAllValuesTenTimesTheKey = myMap.forall { case (k, v) => k * 10 == v }
The problem is that forall wants a function that takes a single Tuple2, rather than two arguments. (We're thinking of a Map[A,B] as an Iterable[(A,B)] when we use forall.) Using a case statement is a nice workaround; it's really using pattern matching here to break apart the Tuple2 and give the parts names.
If you don't want to use pattern matching, you could have also written
val areAllValuesTenTimesTheKey = myMap.forall(p => p._1 * 10 == p._2 }
but I think that's less helpful.
forall is passed a single (Int, Int) Tuple (as opposed to multiple parameters). Consider this (which explicitly shows a single tuple value is decomposed):
val areAllValuesTenTimesTheKey = myMap.forall(t => t match { case (k, v) => k * 10 == v })
Or, the short-hand (which actually passes a PartialFunction):
val areAllValuesTenTimesTheKey = myMap.forall {case (k, v) => k * 10 == v}
(These both decompose the tuple take in.)
Additionally, the function can be "tupled"ed:
val myMap = Map((1,10), (2,20))
val fn = (k: Int, v: Int) => k * 10 == v
val tupled_fn = fn.tupled
val areAllValuesTenTimesTheKey = myMap.forall(tupled_fn)
myMap: scala.collection.immutable.Map[Int,Int] = Map((1,10), (2,20))
fn: (Int, Int) => Boolean = // takes in two parameters
tupled_fn: ((Int, Int)) => Boolean = // note that it now takes in a single Tuple
areAllValuesTenTimesTheKey: Boolean = true
Happy coding.
The problem with your code, is that you give forall method a function, that accepts 2 arguments and returns Boolean, or in other words (Int, Int) => Boolean. If you will look in the documentation, then you will find this signature:
def forall (p: ((A, B)) => Boolean): Boolean
in this case forall method expects Tuple2[A, B] => Boolean, so it also can be written like this:
def forall (p: Tuple2[A, B] => Boolean): Boolean
In order to fix your example you can either call forall and give it function, that accepts 1 tuple argument:
myMap.forall(keyVal => keyVal._1 * 10 == keyVal._2)
or you make patterns match and extract key and value:
myMap.forall {case (k, v) => k * 10 == v}
In this case you are giving PartialFunction[(Int, Int), Boolean] to the forall method