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
吗?
答案 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)
我觉得在你的情况下更有意义。