1

Following function accepted more or less any collection and returned it filtered:

def filterEven[Repr](o: collection.IterableLike[Int, Repr]): Repr = {
  o.filter { o =>
    (o % 2) == 0
  }
}

filterEven(List(1, 2, 3))

filterEven(Set(1, 2, 3))

How do I achieve the same with Scala 2.13? IterableLike no longer exists there. Should I use higher kinded types somehow?

Suma
  • 33,181
  • 16
  • 123
  • 191

1 Answers1

3

It seems higher kinded types together with IterableOps can be used to achieve this:

def filterEven[CC[Int] <: IterableOps[Int, CC, CC[Int]]](o: CC[Int]): CC[Int] = {
  o.filter { o =>
    (o % 2) == 0
  }
}

I found this more logical than the previous Repr based solution.

Inspired by Adding custom collection operations in scala 2.13 to arbitrary collections of specific types

Suma
  • 33,181
  • 16
  • 123
  • 191
  • That won't let you use types like `BitSet`, not sure if that is ok or not for your use case. – Luis Miguel Mejía Suárez Aug 10 '21 at 16:15
  • My Scala 2.12 was for Iterables only as well, therefore it is OK for my use (I need List and Set). Your `IsIterable` solution looks nice as well. It feels a bit strange `BitSet` has `IsIterable`, but `IterableOps` do not accept it. – Suma Aug 10 '21 at 16:21
  • Yeah, the whole stdlib collections hierarchy is weird, I gave up on trying to understand it years ago; I just use **cats** typeclasses when it makes sense and a couple of `IsIterableOnce` to accept anything. – Luis Miguel Mejía Suárez Aug 10 '21 at 17:45
  • 1
    You can still use `IterableOps` for stuff like BitSet with two type parameters: `def filterEven[CC[_], C](col: IterableOps[Int, CC, C]): C`. It will convert Array to ArraySeq though since Array doesn't extend IterableOps – Oleg Pyzhcov Aug 11 '21 at 08:55