Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing parameter type

Tags:

types

scala

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

like image 244
Electric Coffee Avatar asked Mar 01 '16 10:03

Electric Coffee


3 Answers

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)
}    
like image 60
Mikesname Avatar answered Oct 19 '22 12:10

Mikesname


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)
like image 44
hasumedic Avatar answered Oct 19 '22 12:10

hasumedic


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.

like image 25
slouc Avatar answered Oct 19 '22 12:10

slouc