1

Below are my method signatures and definitions in scala

  def accumulate[T[_]: Traversable, O: Monoid, A]: (A => O) => T[A] => O =
    fao => ta =>
      (implicitly[Traversable[T]].traverse[({type f[X] = Acc[O, X]})#f, A, O](ta)(a => Acc(fao(a)))).value

  def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = to => accumulate[T, O, O](a => a)(to)

However I get the following error for my definition of reduce

Error:(160, 82) not enough arguments for method accumulate: (implicit evidence$7: Traversable[T], implicit evidence$8: Monoid[O])(O => O) => (T[O] => O).
Unspecified value parameter evidence$8.
  def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = to => accumulate[T, O, O](a => a)(to)
                                                                                 ^

Not sure where I am going wrong. Any help would be appreciated.

Thanks!

Abdul Rahman
  • 1,294
  • 22
  • 41
  • 1
    It would make it easier if you provided a reference to the implementations of Traversable/Monoid/Acc, afaik scala's built in traversable doesn't have a traverse method though the Traverse type class in both scalaz and cats do. – Angelo Genovese Oct 22 '16 at 19:58
  • @AngeloGenovese it's safe to assume there's only one (lawful) implementation of `Traversable` or `Monoid` that he can be referring to here, that is the usual one you can find in `scalaz` or `cats`. – Yawar Oct 22 '16 at 20:05
  • @Yawar fair, but it also means that in order to try to reproduce his issue I spent time figuring out what Acc looked like, and remembering that the scala collections Traversable isn't the same as the Traverse type class. Oddly enough, using cats and a dummy impl of Acc I don't get the same compile error on scala 2.10. (scratch that, just my IDE hiding things from me) – Angelo Genovese Oct 22 '16 at 20:11
  • @AngeloGenovese The compiler complains when I add definition of reduce, when i take out reduce code compiles so not sure if knowing impl for traversable/monoid/acc would provide additional information in that case. Let me know if you still want me to add them and I can add them then. – Abdul Rahman Oct 22 '16 at 20:13

1 Answers1

2

You are getting tripped up by the hidden (implicit) parameters to the accumulate method. The context bounds you've placed on it mean that the method really has the following type signature:

def accumulate[T[_], O, A](
  implicit traversable: Traversable[T],
  monoid: Monoid[O]): (A => O) => T[A] => O

In fact I'd advise you to not use context bounds if you actually do need to use their corresponding implicits in your methods (as opposed to just implicitly passing them in to another method). It's much clearer to type out the implicits explicitly (ironically).

So, what's happening in reduce is that you're trying to pass in the function a => a in the position where the compiler is expecting the two implicit arguments of Traversable[T] and Monoid[O]. The solution is to either pass in the implicits explicitly, or monomorphise accumulate before calling it:

def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = { to =>
  // This forces the compiler to pass in the correct implicits
  val accumulate_ = accumulate[T, O, O]
  accumulate_(a => a)(to)
}
Yawar
  • 11,272
  • 4
  • 48
  • 80
  • Thanks! That works. But why would this not work accumulate(Traversable[T], Monoid[O])(a => a)(to) as well from what you wrote. This gives me a compile error. – Abdul Rahman Oct 22 '16 at 20:30
  • @AbdulRahman hmm, maybe `Traversable.apply` and `Monoid.apply` are not defined to return the correct implicits? Can you post the compile error message? – Yawar Oct 22 '16 at 20:33
  • Error:(162, 27) object Traversable does not take type parameters. accumulate(Traversable[T], Monoid[O])(a => a)(to) Error:(162, 38) object Monoid does not take type parameters. accumulate(Traversable[T], Monoid[O])(a => a)(to) ^ – Abdul Rahman Oct 22 '16 at 20:35
  • @AbdulRahman yeah, so `Traversable.apply` and `Monoid.apply` are definitely not defined. That syntax would have worked if they were. Otherwise you'll need to do `accumulate(implicitly[Traversable[T]], implicitly[Monoid[O]])(a => a)(to)` but in that case you might as well declare the implicit parameters explicitly like I mentioned. – Yawar Oct 22 '16 at 20:38