使用集合作为函数

时间:2013-09-25 04:01:44

标签: scala functional-programming abstraction higher-order-functions

来自FP课程:

type Set = Int => Boolean  // Predicate

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

为什么这才有意义?

assert(contains(x => true, 100))

它的基本功能是为函数100提供值x => true。即,我们提供100,它返回 true

但这与集合有什么关系?

无论我们放什么,它都会返回true。感觉在哪里?

我知道我们可以提供我们自己的set实现/函数作为一个参数来表示提供的值在一个集合内部(或者不是) - 然后(仅)这个实现使得contains函数成为由某种意义/意义/逻辑/功能填补。

但到目前为止它看起来像一个无意义的功能。它名为contains,但名称不代表逻辑。我们可以称之为apply(),因为它的作用是将一个函数(第一个参数)应用于一个值(第二个参数)。仅使用名称contains可以告诉读者作者可能想说什么。是不是太抽象了,也许?

2 个答案:

答案 0 :(得分:7)

在上面显示的代码段中,任何集合S都由所谓的特征函数表示,即给定一些整数i的函数检查是否i中的S 是否包含。因此,您可以将这样一个特征函数f想象成一个集合,即

  

{i | if i}

的所有整数true

如果您考虑任何类型为Int => Boolean的函数(由类型同义词Set = Int => Boolean表示),那么您可以通过

描述contains
  

给定一组f和一个整数icontains(f, i)会检查i是否为f的元素。

一些示例集可能会使这个想法更加明显:

Set                                Characeristic Function
 empty set                          x => false
 universal set                      x => true
 set of odd numbers                 x => x % 2 == 1
 set of even numbers                x => x % 2 == 0
 set of numbeers smaller than 10    x => x < 10

示例:集合{1,2,3}可以用

表示
val S: Set = (x => 0 <= x && x <= 3)

如果您想知道某个号码n是否在此集合中,您可以

contains(S, n)

但当然(正如你已经观察过的那样)你可以通过直接做

得到相同的结果
S(n)

虽然这个更短,但前者可能更容易阅读(因为意图有点明显)。

答案 1 :(得分:2)

集(在数学上和在计算机表示的上下文中)可以以各种不同的方式表示。使用特征函数是一种可能性。该想法是给定通用集合U的子集S完全由函数f确定:U - > {真,假}(称为子集的特征函数)。只是因为你可以将f(u)视为回答问题&#34;你是S中的元素吗?&#34;。

与其他方法相比,任何特定的代表集选择都有其优点和缺点。特别是,某些表示更适合用功能语言建模而不是命令式语言。如果我们将管理集作为特征函数与(排序或未排序)列表(或数组)进行比较,那么,例如,创建联合,交集和集合差异,对于特征函数非常有效,但对列表效率不高。检查元素的存在就像使用特征函数计算f( - )一样简单,而不是搜索列表。但是,使用列表立即打印出集合中的元素,但可能需要大量具有特征函数的计算。

话虽如此,一个根本的区别在于,对于特征函数,人们可以对无限集进行建模,而这对阵列来说是不可能的。当然,没有集合实际上是无限的,但是像(x:BigInt)x =&gt;这样的集合。 (x%2)== 0真正代表所有偶数整数的集合,并且实际上可以用它计算(只要你不尝试打印所有元素)。

所以,每个代表都有利有弊(duh)。