4

我有一个函数map,它接受一个Parser和一个定义如下的函数:

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

我创建了一个Parser类型的对象[(Char, Char)]和一个函数(Char, Char) => String

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

然后我将这两个传递给map函数。

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

我希望一切正常,但我得到一个asString参数类型不匹配错误说

错误:(26, 41) 类型不匹配;

发现:(字符,字符)=>字符串

必需: ((Char, Char)) => 字符串

地图[(字符,字符),字符串](解析器,asString)

我试图明确指定mapas的类型,map[(Char, Char), String](parser, asString)但这也无济于事。

这里的类型T1是 char 元组(Char, Char)并且T2String. 因此,该函数(Char, Char) => String应该是输入,但 scala 期待不同的类型。

我在这里想念什么?为什么期待((Char, Char)) => String而不是(Char,Char) => String

我正在使用 Scala 2.12。不知道这是否相关。

感谢您的帮助。

4

2 回答 2

3

该类型(Char, Char) => String对应于一个接受两个 Char 参数并返回一个 String 的函数。

你想要的是一个接受 aTuple2并返回一个 String 的函数,它在某种程度上是不同的。

它的类型应该是Tuple2[Char, Char] => String. Tuple2[Char, Char]对应于类型简写(Char, Char),但我猜在函数定义期间编译器将括号解释为好像它们用于对函数参数进行分组。

这是一个已知问题,正在 scala3 中解决。 https://dotty.epfl.ch/docs/reference/auto-parameter-tupling.html

于 2018-07-20T07:37:01.550 回答
2

正如其他人指出的那样,定义一个接受一个Tuple2而不是两个参数的函数会有点棘手,而且看起来很丑陋。

一个很好的解决方法是使用.tupled

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

FunctionN.tupled将接受 N 个参数的函数转换为接受 a 的等效函数TupleN。这比定义一个元组获取函数要好一些,因为您遇到了括号怪癖,而且您不必解构主体中的元组。

于 2018-07-20T17:01:19.137 回答