我有一个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)类型不匹配;
found:(Char,Char)=>字符串
必填:((Char,Char))=>字符串
map [(Char,Char),String](解析器,asString)
我尝试将map
的类型显式指定为map[(Char, Char), String](parser, asString)
,但这也无济于事。
这里的类型T1
是字符元组(Char, Char)
,而T2
是String
。因此,功能(Char, Char) => String
应该是输入,但是scala期望使用其他类型。
我在这里想念什么?为什么会期望((Char, Char)) => String
而不是(Char,Char) => String
?
我正在使用Scala 2.12。不知道这是否有任何意义。
感谢您的帮助。
答案 0 :(得分:2)
类型(Char, Char) => String
对应于一个带有两个Char参数并返回String的函数。
您想要的是一个函数,该函数需要一个Tuple2
并返回一个有所不同的String。
其类型应为Tuple2[Char, Char] => String
。
Tuple2[Char, Char]
对应于类型简写(Char, Char)
,但是我猜想在函数定义期间,编译器将括号解释为好像它们用于对函数参数进行分组一样。
这是一个已知问题,已在scala3中解决。 https://dotty.epfl.ch/docs/reference/auto-parameter-tupling.html
答案 1 :(得分:1)
正如其他人指出的那样,定义一个接受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个参数的函数转换为带有TupleN
的等效参数。
这比定义元组获取函数要好一些,这是因为您遇到了括号中的怪癖,而且还因为您不必在体内分解元组。