Search code examples
scalafunctional-programmingsetfoldleft

How to make accumulator an Empty Set of Int in Scala foldLeft?


I currently have a Set in Scala of size greater than 1 :

val x = BitSet(19, 49) and
val z = HashMap(49 -> HashSet(5, 6, 9, 13, 3, 8, 4), 19 -> Set(5, 9, 14)) of type Map[Int,Set[Int]]

I am trying to construct a Set[Int] having all values associated to the element in Set x using foldLeft, the end result would be: HashSet(5, 6, 9, 13, 3, 8, 4, 14), but I am not able to correctly set the accumulator as a Set[Int].

I am not using x.foldLeft(Set(0))((acc, elem) => acc.union(z(elem))) and then removing the element 0 from the final set.

I tried x.foldLeft(Set.empty)((acc, elem) => acc.union(z(elem)))

type mismatch found   : 
Set[Int]     (in scala.collection.immutable) 
required: Set[Nothing] (in scala.collection) 

I even tried creating an empty Set[Int] as a variable and using it in fold expression but It also did't work. I cannot keep Set(0) as initial value of the accumulator since it might occur as an actual value.


Solution

  • Except for 1 minor mistake, the code is perfectly fine. x.foldLeft(Set.empty)((acc, elem) => acc.union(z(elem)))

    There are ways to fix this:

    1. x.foldLeft(Set.empty[Int])((acc, elem) => acc.union(z(elem)))
    2. x.foldLeft[Set[Int]](Set.empty)((acc, elem) => acc.union(z(elem)))
    

    TL;DR

    If we dig deeper int the scala code this is the signature of foldleft

    def foldLeft[B](z: B)(op: (B, A) => B): B

    There are 2 parts of this curry function, where first onedef foldLeft[B](z: B) while the second part contains op which will be applied during iteration.

    Let's understand how the compiler will infer the Generics. x.foldLeft[?](Set.empty[?]) here in the Set.empty question mark will be replaced with a default Nothing but in ops function the parameter acc has the type of Set[int]. This will cause a type mismatch.

    To fix the compilation issue, either we need to supply the type parameter in the Set.empty or explicitly provide type before the foldLeft so that Set.empty the correct type will be infrared by the compiler.