我试图理解类型别名是如何工作的,并且通过扩展,如何在Set
上建模的简单type Set = Int => Boolean
类型将被重写为具有部分函数的类。
背景:据我所知,我可以像上面一样创建一个类型别名,并将其用作简单的功能集数据类型:
type Set = Int => Boolean
def union(s: Set, t: Set): Set = (x => s(x) || t(x))
def contains(s: Set, n: Int): Boolean = s(n)
val s1 = Set(3)
val s2 = Set(7)
val u1 = union(s1, s2)
contains(u1, 3) // res4: Boolean = true
一切都很好。需要一些思考,但我知道它是如何工作的; u1
基本上成为部分功能:
union(s: (Int => Boolean), t: (Int => Boolean)): Int => Boolean
所以如果我想把它变成一个类,我的第一次尝试就是这样:
case class Set(v: Int) {
def apply(i: Int) = i == v
def contains(n: Int): Boolean = this(n)
def union(n: Set): Set = (x => n(x) || apply(x)) // Missing param
}
但这不起作用(union
的定义有编译错误,x
是缺少的参数)。
在摆弄了一段时间后,我不知道如何在不采用更强制性的方法(如实际创建基于集合的Set类)的情况下实现类似的类型。必须有一种方法以纯粹的功能方式做到这一点......
答案 0 :(得分:1)
您需要包裹Int => Boolean
,而不是Int
。所以
case class Set(f: Int => Boolean) {
def apply(i: Int) = f(i)
def union(s: Set) = Set(x => this(x) || s(x))
// or Set(union(f, s.f)) to use existing definition of union
}
对于您自己对Set
的定义,apply
使其成为单元素集,因此您无法定义union
:两个单元素的并集也就不足为奇了集合可以有多个元素。
Scala具有值和类型的单独名称空间。 type Set
或class Set
仅定义类型 Set
,而val Set
,object Set
或var Set
定义值,并且case class
定义了两者。现在,Set(3)
需要一个名为Set
的值;在您的第一个代码示例中没有这样的值,因此它使用scala.Predef
中的一个,它是自动导入的。 scala.Predef.Set(3)
会返回scala.collection.Set[Int]
,这恰好会扩展Int => Boolean
,这就是union(s1, s2)
编译的原因。 case class
定义了类型和的值;因此,上面的代码Set(3)
无法编译,因为使用此值而不是scala.Predef.Set
。