2014-11-01 69 views
1

我试着写了下面的方法进行串联3只列出了一起:Scala中使用“_”代替显式类型

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] 

回答

6

我知道至少有2种方法来做到这一点:

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是咖喱功能类型A =>的TypeB => TypeC = > TypeD(所有类型都等于列表)

所以你还是要使用_ ++ _ ++ _你需要将你的函数转换为3输入函数(或者Tuple3的函数值=>东西)

1

您遇到的问题是由于可以定义Scala函数的各种方式。首先是具有诸如(T1, T2, ...) => RetType之类的签名的“正常”非咖喱功能。

然后存在形式为T1 => T2 => ... => RetType的curried函数,它基本上是一个高阶1参数函数链,它返回其他1参数函数,并且链的末尾返回实际的返回值。为什么这是有用的,谷歌像“斯卡拉curried功能”。

表达式_ <someoperator> _ <someoperator> _ ...返回非curry函数,因为这些是Scala中的默认函数。因此,如果您声明foo返回T1 => T2 => ... => RetType但实际上您返回(T1, T2, ...) => RetType,则类型签名将不匹配并且scalac将发生抱怨。

的解决方案是同时使用咖喱签名以及一个咖喱函数作为返回值:

def foo1[T]: List[T] => List[T] => List[T] = 
    a => b => a ++ b 

或使用uncurried签名和uncurried返回值:

def foo2[T]: (List[T], List[T]) => List[T] = 
    _ ++ _ 

后者相当于:

def foo2[T]: (List[T], List[T]) => List[T] = 
    (a, b) => a ++ b 

另一种替代方案是让斯卡拉转换您uncurried功能成咖喱之一:

def foo2[T]: List[T] => List[T] = (_ ++ _).curried 

... ,由于是出这个问题的范围的原因,类型inferencer韩元不可能有太多的用途,所以你必须首先注释并丢失_的简洁性:

def foo2[T]: List[T] => List[T] = ((_: List[T]) ++ (_: List[T])).curried