2016-06-27 52 views
0

可以开始值只是op参数列表中的参数?为什么折咖喱?

食品是在列表定义为

DEF折叠[A1>:A](Z:A1)(OP:(A1,A1)⇒A1):A1裥元素此横越的 或迭代器使用指定的关联二进制运算符 。

什么会折叠限定为

的含义DEF折叠[A1>:A](OP:(Z:A1,A1,A1)⇒A1):A1

所以在这个版本中,初始值作为一个值传递给函数,而不是在单独的参数列表中被curry。

+1

第二个选项意味着在每个调用'op',初始值必须被传递,这是不必要的(为什么会'op'需要接收在每个呼叫的初始值?)。 – Jesper

+0

但是,在将'z'从何而来,如果'需要op'与它叫,但你不将它传递给'fold'? – Bergi

+0

@Bergi代替运算:(Z:A1,A1,A1)使用运算:(A1,A1,A1),类型A1是在类级类型的。这会工作吗? –

回答

4

如果您想要激发foldLeft的特定签名,首先检查reduceLeft可能是值得的。

// Slightly simplified to remove the supertype constraint 
def reduceLeft(f: (A, A) => A): A 

reduceLeft squishes整个集合到一个单一的元素,它需要作为一个参数,告诉它如何将集合中的每个新元素压扁到什么它这么远的功能。

有,然而,一个问题。 reduceLeft是部分。特别是如果收集是空的,reduceLeft无处开始压扁东西。所以我们可以通过告诉reduceLeft从哪里开始做到这一点。所以我们给reduceLeft一个额外的参数。

def reduceLeftTotal(initial: A, f: (A, A) => A): A 

注意,如果我们只是glommed initial作为另一个参数f,我们不会解决的reduceLeft偏颇。如果this是一个空集合,我们仍然炸毁。

// This doesn't get us what we want. Where does the initial `A` come from? 
def reduceLeftNotWhatWeWant(f: (A, A, A) => A): A 

好了,现在我们已经有了reduceLeftTotal,有泛化立即新途径。为什么我们要压缩集合中所有元素的东西必须具有与元素相同的类型?答案是不是!

def generalReduceLeftTotal[B](initial: B, f: (B, A) => A): B 

最后,由于在之前的参数列表,但在同一列表中没有先前的参数类型信息,可被用来帮助Scala的类型推断,我们可以减少显式类型注解,我们需要通过讨好量。

// And we're back to foldLeft! 
def foldLeft[B](initial: B)(f: (B, A) => A): B