我尝试编写以下方法将3个列表连接在一起:
def f[A]: List[A] => List[A] => List[A] => List[A] = _ ++ _ ++ _
但得到了这个编译时错误消息:
<console>:7: error: missing parameter type for expanded function
((x$1, x$2, x$3) => x$1.$plus$plus(x$2).$plus$plus(x$3))
def f[A]: List[A] => List[A] => List[A] => List[A] = _ ++ _ ++ _
是否可以比以下更简洁地编写它:
scala> def f[A](xs: List[A], ys: List[A], zs: List[A]) = xs ++ ys ++ zs
f: [A](xs: List[A], ys: List[A], zs: List[A])List[A]
答案 0 :(得分:6)
我至少知道两种方法:
def f[A]: List[A] => List[A] => List[A] => List[A] =
a => b => c => a ++ b ++ c
def f2[A]: (List[A], List[A], List[A]) => List[A] =
_ ++ _ ++ _
val l1 = List(1)
val l2 = List(2)
val l3 = List(3)
println(f(l1)(l2)(l3))
println(f2(l1, l2, l3))
您的原始_ ++ _ ++ _是具有3个参数的函数的占位符,但您的f是curried函数TypeA =&gt; TypeB =&gt; TypeC =&gt; TypeD(所有类型都等于List)
所以你仍然想使用_ ++ _ ++ _你需要将你的函数转换为3输入函数(或者Tuple3 =&gt;某事物的函数值)
答案 1 :(得分:1)
您遇到的问题是由于可以定义Scala函数的各种方式。首先是&#34;正常&#34;带有(T1, T2, ...) => RetType
等签名的非curried函数。
然后有T1 => T2 => ... => RetType
形式的curried函数,它本质上是一个高阶1参数函数链,返回其他1参数函数,链的末尾返回实际的返回值。为什么这很有用,请谷歌搜索&#34; scala curried functions&#34;。
表达式_ <someoperator> _ <someoperator> _ ...
返回非curried函数,因为它们是Scala中的默认函数。因此,如果您声明foo
要返回T1 => T2 => ... => RetType
但实际上返回(T1, T2, ...) => RetType
,则类型签名将不匹配,scalac
会抱怨。
解决方案是使用curried签名和curried函数作为返回值:
def foo1[T]: List[T] => List[T] => List[T] =
a => b => a ++ b
或使用未经签名的签名和未经证实的返回值:
def foo2[T]: (List[T], List[T]) => List[T] =
_ ++ _
后者相当于:
def foo2[T]: (List[T], List[T]) => List[T] =
(a, b) => a ++ b
另一个替代方案是让Scala将未经验证的功能转换为有条件的功能:
def foo2[T]: List[T] => List[T] = (_ ++ _).curried
... 但,由于超出此问题范围的原因,类型推断器无法使用,因此您必须注释和首先失去_
的简洁性:
def foo2[T]: List[T] => List[T] = ((_: List[T]) ++ (_: List[T])).curried