1

I'm trying to implement a function that operates with traversable object.

def f[V, M[_] <: Traversable[_]](ei: M[V])(builder: GenericCompanion[M]): M[V] =
  ei.foldLeft(builder.empty[V])((accum: M[V], el: V) => builder(el))

This code doesn't compile because of

Error:(22, 57) type mismatch;
 found   : el.type (with underlying type Any)
 required: V
  ei.foldLeft(builder.empty[V])((accum, el) => builder(el))
                                                       ^

Reproduced with scala 2.11.8 and 2.12.1. It's bizarre. Why el is assumed as Any?


I could solve it with cats library. So question is not 'How to do it?' but 'Why pure scala code is wrong?'.

def f[V, M[_] : Foldable : Alternative](ei: M[V]): M[V] = {
  val monoidK = implicitly[MonoidK[M]]

  ei.foldLeft(monoidK.empty[V]) {
    (accum, el) => monoidK.algebra[V].combine(accum, el.pure[M])
  }
}
Zernike
  • 1,758
  • 1
  • 16
  • 26

1 Answers1

1

Looks like the problem with _ in type bounds, after replacing it with a letter X it compiles.

def f[V, M[X] <: Traversable[X]](ei: M[V])(builder: GenericCompanion[M]): M[V] =
  ei.foldLeft(builder.empty[V])((accum: M[V], el: V) => builder(el))

Take a look at this answer for some intuition. As I understand

M[_] <: Traversable[_] is M that extends Traversable[Any] and has some type hole. In other words it fills type hole in Traversable with Any and then creates a new type hole in M (that you don't need).

M[X] <: Traversable[X] synchronizes type holes in M and Traversable. So whatever type is put in M it will be placed in Traversable

Nazarii Bardiuk
  • 4,272
  • 1
  • 19
  • 22