4
votes

I have a function map which takes a Parser and a function defined as follows:

def map[T1, T2](parser: Parser[T1], func: T1 => T2): Parser[T2]

I've created a Parser object of type [(Char, Char)] and a function (Char, Char) => String.

val parser[(Char,Char)] = //...
val asString: (Char, Char) => String = (a: Char, b: Char) => a.toString + b.toString

And then I pass these two to the map function.

val mParser: Parser[String] = map(parser, asString)

I expect everything to work fine but I get a type mismatch error for asString argument saying

Error:(26, 41) type mismatch;

found : (Char, Char) => String

required: ((Char, Char)) => String

map[(Char, Char), String](parser, asString)

I have tried to explicitly specify the types for map as map[(Char, Char), String](parser, asString) but that didn't help either.

The type T1 here is the char tuple (Char, Char) and T2 is a String. So, the function (Char, Char) => String is what's supposed to be the input but scala is expecting a different type.

What am I missing here? Why is it expecting ((Char, Char)) => String instead of (Char,Char) => String?

I'm using Scala 2.12. Don't know if that is relevant in any way.

Your help is appreciated.

2
Can you try map(parser -> asString) ? Here you can get more information about Map.tea-addict
What is that? I''m not using a Hashmap. I'm talking about the map function I've defined.Durga Swaroop
Sorry, I missed thattea-addict

2 Answers

3
votes

The type (Char, Char) => String corresponds to a function that takes two Char parameters and returns a String.

What you want is a function that takes a Tuple2 and returns a String which is somehow different.

Its type should be Tuple2[Char, Char] => String. Tuple2[Char, Char] corresponds to the type shorthand (Char, Char) but I guess during function definition the compiler interprets the parentheses as if they are used to group the function parameters.

This is a known issue and it's being addressed in scala3. https://dotty.epfl.ch/docs/reference/auto-parameter-tupling.html

2
votes

As others pointed out, defining a function, that accepts a Tuple2 rather than two parameters, gets a little tricky, and ugly-looking.

A nice way around that is to use .tupled:

 val asString: (Char, Char) => String = (a: Char, b: Char) => a.toString + b.toString
 val mParser: Parser[String] = map(parser, asString.tupled)

FunctionN.tupled converts a function accepting N arguments into an equivalent one taking a TupleN. This is a bit nicer than defining a tuple-taking function, because of the parenthesis quirks you ran into, and also, because you don't have to deconstruct the tuple in the body.