セットS
と別のセットT
がある場合T = S ∪ {x}
(つまり、1つの要素が追加されている場合)、---のべき集合T
は次の ように表すことができます。S
T
P(T)
P(S)
x
P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }
つまり、べき集合を再帰的に定義できます(これにより、べき集合のサイズが無料で得られることに注意してください。つまり、1要素を追加するとべき集合のサイズが2倍になります)。したがって、次のように、scalaでこの末尾再帰を実行できます。
scala> def power[A](t: Set[A]): Set[Set[A]] = {
| @annotation.tailrec
| def pwr(t: Set[A], ps: Set[Set[A]]): Set[Set[A]] =
| if (t.isEmpty) ps
| else pwr(t.tail, ps ++ (ps map (_ + t.head)))
|
| pwr(t, Set(Set.empty[A])) //Powerset of ∅ is {∅}
| }
power: [A](t: Set[A])Set[Set[A]]
それで:
scala> power(Set(1, 2, 3))
res2: Set[Set[Int]] = Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3), Set(1, 2))
List
実際には、 (つまり再帰的なADT)で同じことを行う方がはるかに見栄えがします。
scala> def power[A](s: List[A]): List[List[A]] = {
| @annotation.tailrec
| def pwr(s: List[A], acc: List[List[A]]): List[List[A]] = s match {
| case Nil => acc
| case a :: as => pwr(as, acc ::: (acc map (a :: _)))
| }
| pwr(s, Nil :: Nil)
| }
power: [A](s: List[A])List[List[A]]