Perl6で開基から開集合系を生成する

10年ぶりくらいにPerl触ってます。RubyPythonより好きです。

コード

((1).Set, (2, 3).Set, (2).Set).combinations.map({.reduce(&infix:<∪>)}).Set.say;
> set(set() set(1 2 3) set(1 2) set(1) set(2 3) set(2))

解説

((1).Set, (2, 3).Set, (2).Set)

開基です。Xとします。

.combinations

冪集合2^{X} (の部分集合)を求めるメソッドです。ちなみに後ろに数値を指定すると、その位数の集合だけ取り出せます。 この場合、

()
(set(1))
(set(2 3))
(set(2))
(set(1) set(2 3))
(set(1) set(2))
(set(2 3) set(2))
(set(1) set(2 3) set(2))

となります。

.map({.reduce(&infix:<∪>)})

2^{X}の各元に.reduce(&infix:<∪>)を適用します。
reduceは配列の要素に対してbinary operatorを順番に適用し、その結果を返します。
&infix:<∪>は記号の通り、集合のunionをとるので、各B \in 2^{X}に対して、\bigcup_{A \in B}Aを返します。

結果はリストなので、.Setで重複を取り除きます。

ひとこと

集合の演算をそのまま数学記号でかけるので分かりやすいですが、打ちにくいです。
今回はinfixの形で利用しましたが、普通の演算子と同じように使うこともできます。

参照

https://docs.perl6.org/language/setbagmix
https://docs.perl6.org/type/Array