2017-05-25 52 views
2

如何構造一個函數,其中apply需要多個參數?構成多個參數的Scala函數

這是一個人爲的例子:

val sum: List[Int] => Int = l => l.sum 

val double: Int => Int = i => i * i 

double.compose(sum).apply(List(1,2,3)) //=> 36 

val sumAppend: (List[Int], Int) => Int = (l, i) => i :: l sum 

double.compose(sumAppend).apply(List(1,2,3), 1) // Attempt to append 1 to list then sum 

上面給我一個類型推斷的錯誤?

回答

2

定義compose2,例如作爲一個擴展方法Function1

implicit class ComposeFunction2[A, B, C, D](f1: Function1[C, D]) { 
    def compose2(f2: Function2[A, B, C]): Function2[A, B, D] = 
    (a: A, b: B) => f1(f2(a, b)) 
} 

這將是比快的替代品,因爲它不分配的元組。用法:

scala> val double: Int => Int = i => i * i 
double: Int => Int = <function1> 

scala> val sumAppend: (List[Int], Int) => Int = (l, i) => i :: l sum 
sumAppend: (List[Int], Int) => Int = <function2> 

scala> double.compose2(sumAppend).apply(List(1,2,3), 1) 
res5: Int = 49 
1

在這種情況下,您可以只編寫帶有單個參數的函數。所以sumAppend必須是一個函數,它接受任何類型的單個參數,並且必須返回Int的結果(即_ => Int)。

您可以將一個帶有兩個參數的函數轉換爲一個curried函數,並部分應用該函數,如下所示。

scala> val sumAppend = (l: List[Int], i: Int) => (i :: l).sum 
sumAppend: (List[Int], Int) => Int = $$Lambda$1630/[email protected] 

scala> double.compose(sumAppend.curried.apply(List(1,2,3))).apply(10) 
res18: Int = 256 

另一個選擇是讓sumAppend接受一個單參數,它是List [Int]和Int的元組。

scala> val sumAppend: ((List[Int], Int)) => Int = l => (l._2 :: l._1).sum 
sumAppend: ((List[Int], Int)) => Int = $$Lambda$1597/[email protected] 

scala> val x = double.compose(sumAppend).apply((List(1,2,3),10)) 
x: Int = 256