foldLeft参数签名:o

时间:2017-07-10 09:06:05

标签: scala

type Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = s(elem)
def union(s: Set, t: Set): Set = (x => contains(t,x) || contains(s,x))
def singletonSet(elem: Int): Set = (x => x==elem)

...

val s1 = singletonSet(1)
val s2 = singletonSet(2)
val s3 = singletonSet(3)

// works
val s = List(s1,s2,s3).foldLeft( union(_,_) )

// error
val s = List(s1,s2,s3).foldLeft( union )

为什么第二种方式不起作用?它说我工会的签名是错的!

但是如果我使用像union(_, _)这样的通配符参数,它就有效。我不能像第二个例子那样使用union吗?

1 个答案:

答案 0 :(得分:1)

foldLeft的定义如下:

def foldLeft[B](z: B)(op: (B, A) ⇒ B): B

第一个参数是'零',所以首先传递给fold函数的元素(第二个参数)。因此,在第一种情况下,您将函数union作为零参数(仅参数)传递。添加类型注释时会很清楚:

val sU1: (((Set, Set) => Set, Set) => (Set, Set) => Set) => (Set, Set) => Set = List(s1,s2,s3).foldLeft( union(_,_) )

如果你只给foldLeft的零参数(关键词currying)你得到一个函数,把一个函数作为参数。参数函数获取列表中元素类型的元素和零参数(所以Set和union类型 - > (Set, Set) => Set)并返回零参数类型的元素(所以在你的第一种情况下再次使用(Set, Set) => Set)类型的函数。

你可能想要的是:

val sU2: Set = List(s1,s2,s3).foldLeft(singletonSet(0))(union)

您需要传递一个有效的零参数,然后您可以根据需要使用union函数。

如果您不想提供初始值,则另一个选项是reduceLeft,它会将列表中的第一个元素作为初始值:

val sU3: Set = List(s1,s2,s3).reduceLeft(union)

我觉得在你的情况下更有意义。