I was rewriting a series of Haskell functions in Scala, and ran into a compilation error that I can't seem to explain
The error is as follows:
missing parameter type
def group[A](xs: List[A]): List[List[A]] = groupBy((a, b) => a == b, xs)
^
missing parameter type
def group[A](xs: List[A]): List[List[A]] = groupBy((a, b) => a == b, xs)
^
The code is as follows:
object Stuff {
def main(args: Array[String]): Unit = {
val lst = List(1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 7)
println(group(lst))
}
def group[A](xs: List[A]): List[List[A]] = groupBy((a, b) => a == b, xs)
def groupBy[A](fun: (A, A) => Boolean, input: List[A]): List[List[A]] = // stuff
}
I'm not at all sure what's going on here, why it's complaining about a missing parameter type. As far as I can see everything is defined
It will compile if you provide an explicit generic type argument at the groupBy
call site:
def group[A](xs: List[A]): List[List[A]] = groupBy[A]((a, b) => a == b, xs)
See this post for an explanation of why Scala's type inference is failing for this case.
If you write groupBy
with curried argument lists the type information should be inferred correctly:
def group[A](xs: List[A]): List[List[A]] = groupBy(xs)((a, b) => a == b)
def groupBy[A](input: List[A])(fun: (A, A) => Boolean): List[List[A]] = input match {
case Nil => Nil
case (x::xs) =>
val (ys, zs) = span(fun.curried(x), xs)
(x::ys)::groupBy(zs)(fun)
}
This seems like a limitation of the type inference system. Could you try the following:
def group[A](xs: List[A]): List[List[A]] = groupBy((a: A, b: A) => a == b, xs)
Your function (a, b) => a == b
doesn't specify the type of its arguments. You can easily fix it as:
def group[A](xs: List[A]): List[List[A]] = groupBy((a: A, b: A) => a == b, xs)
or
def group[A](xs: List[A]): List[List[A]] = groupBy[A]((a, b) => a == b, xs)
EDIT:
Another answer has pointed out that it would work if you switched places of parameters and curried them. Yes, because then the second parameter would infer from the first one. Note that second parameter list can learn from the first one, but if they are two parameters in one parameter list then this is not possible (it's in the Scala spec) so that's why we need currying. However, I think it's easier to simply denote the type rather than to switch the parameters and curry the function. Simplicity over unnecessary complications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With