37

我只是想理解下面的代码:


这里声明了一个新类型别名 Set,它是一个接受 Int 参数并返回布尔值的函数

type Set = Int => Boolean

这里声明了一个新方法“contains”,它接受两个类型为 Set 和 Int 的参数,返回一个布尔值。布尔值设置为前面声明的函数 ('type Set = Int => Boolean') 但是执行什么逻辑来确定 Int 'elem' 是否是 Set 's' 的成员

def contains(set: Set, elem: Int): Boolean = set(elem)

这里定义了一个方法,它返回一个返回一个函数的集合?

def singletonSet(elem: Int): Set = set => set == elem

带有注释的完整代码:

  /**
   * We represent a set by its characteristic function, i.e.
   * its `contains` predicate.
   */
  type Set = Int => Boolean

      /**
       * Indicates whether a set contains a given element.
       */
def contains(set: Set, elem: Int): Boolean = set(elem)

      /**
       * Returns the set of the one given element.
       */
      def singletonSet(elem: Int): Set = set => set == elem
4

4 回答 4

99

让我们按逻辑顺序向后阅读。

假设您有一组有限的整数:0, 1, 2, 3, 5, 8例如

描述这组整数的一种方法是通过一个函数(其特征或指示函数),对于每个整数,如果整数在集合中,则返回 true,否则返回 false。正如我们所描述的,这个函数的签名必须始终是Int => Boolean(“给我一个整数,我会告诉你它是否在集合中”),而它的实现将根据具体集合而有所不同。

对于我上面示例中的集合,您可以将此函数简单地编写为:

val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x

或认识到集合中的整数是斐波那契数列的第一个整数,并以稍微复杂的方式定义 f(我不会在这里做......)。请注意,我使用的“包含”是为所有 scala 集合定义的。无论如何,现在你有一个函数可以告诉你什么在集合中,什么不在。让我们在 REPL 中尝试一下。

scala> val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>

scala> mySet(3)
res0: Boolean = true

scala> mySet(9)
res1: Boolean = false

现在, mySet 有 type Int => Boolean,如果我们将其定义为类型别名,我们可以使其更具可读性。

scala> type Set = Int => Boolean
defined type alias Set

除了可读性之外,定义Set为 of 的别名Int => Boolean也明确表明,在某种程度上,集合它的特征函数。Set我们可以使用类型别名以更简洁(但在其他方面等效)的方式重新定义 mySet :

scala> val mySet: Set = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>

现在是这个长答案的最后一部分。让我们定义一个特征函数来描述这个 Singleton 集3:简单的:

val Singleton3 : Set = set => set == 3

对于仅包含 4 个的单例集,它将是:

val Singleton4 : Set = set => set == 4

所以,让我们概括一下这些函数的创建,并编写一个返回单例函数的方法,对于任何整数,该函数描述仅包含该整数的集合:

def singletonSet(elem: Int): Set = set => set == elem

附录:

我跳过了这部分,因为它并不是真正需要的:def contains(set: Set, elem: Int): Boolean = set(elem)

我认为这有点毫无意义,并且(没有更多上下文)它看起来就像一个人为的例子来演示如何将函数作为参数传递,就像 scala 中的任何其他类型一样。它需要Int => Bool函数和Int并且只是将函数应用于Int你可以做

scala> contains(mySet, 3)
res2: Boolean = true

这就像mySet(3)直接打电话一样。

于 2012-10-24T16:26:44.073 回答
5

看了关于“Currying”的讲座视频,相信Paolo用更冗长的方式表达的解决方案是:

    def singletonSet(elem: Int): Set = {
    def innerFunction (givenElement: Int) = 
      if (elem == givenElement) true
      else false
      innerFunction
  }

如果我错了,请纠正我!

于 2013-10-04T05:18:24.900 回答
2

回答您的问题 -但是执行什么逻辑来确定 Int 'elem' 是否是 Set 's' 的成员

这是在您进行实际函数调用时执行的。考虑以下函数调用。

包含(单例集(1),1)

现在 singletonSet 定义为def singletonSet(elem: Int): Set = x => x == elem(为了清楚起见,我选择使用标识符 x)。singletonSet 的返回类型是 Set 类型的函数,它接受一个 Int 参数并返回 Boolean。所以上面调用函数的第一个参数 singletonSet(1) 等于函数x => x == 1因为这里的 elem 是 1。所以我们得到

包含((x => x == 1),1)

现在考虑包含函数def contains(f: Set, elem: Int): Boolean = f(elem)的定义。上面调用中的第一个参数是函数 x => x == 1,它替换了形式参数 f,第二个参数 1 替换了形式参数 elem。contains 的返回值是等于 f(1) 的函数 f(elem)。因为 f(x) 被定义为 (x == 1),所以 f(1) 等于 (1 == 1),它返回 true。

按照相同的逻辑,像 contains(singletonSet(1), 2) 这样的函数调用最终将等同于 (1 == 2),它将返回 false。

于 2016-10-06T13:30:14.213 回答
2

我现在正在上课,也很困惑,但我想我现在明白了。

def singletonSet(elem: Int): Set = (x : Int) => x == elem

这里的 singletonSet 是一个函数,它返回一个 Set 类型的函数,定义为type Set = Int => Boolean

因此,当您调用时def contains(s:Set, elem:Int): Boolean = s(elem),例如:contains(singletonSet(1), 2),singletonSet(1) 正在返回一个函数,其中 elem(在 singletonSet 的定义中)设置为 1,并且 2(也定义为 elem,但在 contains 的参数中定义)被传递在作为singletonSet定义中的x,我们需要摆脱java set的想法,我们不需要singletonSet来持久化我们设置的值。

为了更好地理解,我们可以将参数名称更改如下:

def singletonSet(elemToStore: Int): Set = (x : Int) => x == elemToStore

def contains(s: Set, elemToCheck: Int): Boolean = s(elemToCheck)

于 2018-01-09T19:04:15.997 回答