Reputation: 20436
I have example code:
def test = {
val l : Seq[(String, String)] = Seq()
val foo : (String, String) => Unit = {case (a, b)=>}
l.foreach[Unit](foo)
}
It gives me the next error:
Error:(8, 21) type mismatch;
found : (String, String) => Unit
required: ((String, String)) => Unit
l.foreach[Unit](foo)
As far as I understand foreach
has a type (A=>U)=>Unit
where:
A
is template parameter of my collection andU
is template parameter of foreach
itselfMy question is why is ((String, String)) => Unit
required? Where do the extra brackets come from?
Upvotes: 1
Views: 899
Reputation: 6260
Let's start from top.
You have
val l: Seq[(String, String)]
that is a Seq
of tuples of two strings. So each of the elements of l
is of type (String, String)
which is a syntactic sugar for Tuple2[String, String]
.
Now you have
val foo: (String, String) => Unit
that is a function of two arguments each being String
. Again, the type signature above is syntactic sugar for Function2[String, String, Unit]
.
Considering the above your code can be rewritten as follows:
def test = {
val l: Seq[Tuple2[String, String]] = Seq()
val foo: Function2[String, String, Unit] = {case (a, b)=>}
l.foreach[Unit](foo)
}
foreach
expects a single argument function, i.e. a Function1[T, R]
, thus the type mismatch.
Upvotes: 2
Reputation: 13346
The type definition foo: (String, String) => Unit
says that foo
is a function which takes two parameters of type String
. However, your sequence l: Seq[(String, String)]
contains tuples of type type t = (String, String)
. Thus, calling l.foreach
expects a function which is applicable to the tuple type t
. Thus, it expects a function of type t => Unit
, which is equivalent to ((String, String)) => Unit
.
Upvotes: 1
Reputation: 24802
If you check in the REPL, you'll see that foo
is a <function2>
, that is, a function that takes 2 argument:
scala> val foo : (String, String) => Unit = {case (a, b)=>}
foo: (String, String) => Unit = <function2>
.foreach
however expects a function that takes a single arguement (of type A
), which in your case is a Tuple2
.
If you set foo
to be a <function1>
, then it works:
scala> val foo : ((String, String)) => Unit = {case (a, b)=>}
foo: ((String, String)) => Unit = <function1>
scala> val l : Seq[(String, String)] = Seq()
l: Seq[(String, String)] = List()
scala> l.foreach[Unit](foo)
scala>
Upvotes: 4