代数演算型

badge

代数演算型は、型を代数のようにみなして演算することで生成される型のことです。 代数演算型が扱う演算は、Union, Intersection, Diff, Complementなどがあります。 通常のクラスはUnionのみが行えて、他の演算は型エラーになります。

合併型

Union型では型について複数の可能性を与える事ができる。名前の通り、or演算子で生成されます。 代表的なUnionはOption型です。Option型はT or NoneTypeのpatch typeで、主に失敗するかもしれない値を表現します。

IntOrStr = Int or Str
assert dict.get("some key") in (Int or NoneType)

Option T = T or NoneType

Union型は可換ですが結合的ではないことに注意してください。すなわち、X or Y or Z(X or Y) or ZであってX or (Y or Z)とはなりません。 これを認めると、例えばInt or Option(Str)Option(Int) or StrOption(Int or Str)が同じ型になってしまいます。

交差型

Intersection型は型同士をand演算で結合して得られます。

Num = Add and Sub and Mul and Eq

先述したように通常のクラス同士ではand演算で結合できません。インスタンスは唯一つのクラスに属するからです。

除外型

Diff型はnot演算で得られます。 英文に近い表記としてはand notとした方が良いですが、and, orと並べて収まりが良いのでnotだけで使うのが推奨されます。

CompleteNum = Add and Sub and Mul and Div and Eq and Ord
Num = CompleteNum not Div not Ord

True = Bool not {False}
OneTwoThree = {1, 2, 3, 4, 5, 6} - {4, 5, 6, 7, 8, 9, 10}

否定型

Complement型はnot演算で得られますが、これは単項演算です。not T型は{=} not Tの短縮記法です。 not T型によるIntersectionはDiffと同等で、not T型によるDiffはIntersectionと同等です。 しかしこのような書き方は推奨されません。

# 最も単純な非ゼロ数型の定義
NonZero = Not {0}
# 非推奨のスタイル
{True} == Bool and not {False} # 1 == 2 + - 1
Bool == {True} not not {False} # 2 == 1 - -1

真の代数演算型

代数演算型には、簡約可能な見かけ上の代数演算型とそれ以上簡約できない「真の代数演算型」があります。 そうではない「見かけの代数型」には、Enum型やInterval型、レコード型のorandがあります。 これらは簡約が可能なので真の代数演算型ではなく、型指定に使うとWarningが出ます。Warningを消すためには簡約化するか型定義を行うかする必要があります。

assert {1, 2, 3} or {2, 3} == {1, 2, 3}
assert {1, 2, 3} and {2, 3} == {2, 3}
assert -2..-1 or 1..2 == {-2, -1, 1, 2}

i: {1, 2} or {3, 4} = 1 # TypeWarning: {1, 2} or {3, 4} can be simplified to {1, 2, 3, 4}
p: {x = Int, ...} and {y = Int; ...} = {x = 1; y = 2; z = 3}
# TypeWaring: {x = Int, ...} and {y = Int; ...} can be simplified to {x = Int; y = Int; ...}

Point1D = {x = Int; ...}
Point2D = Point1D and {y = Int; ...} # == {x = Int; y = Int; ...}
q: Point2D = {x = 1; y = 2; z = 3}

真の代数演算型には、Or型、And型があります。クラス同士のorなどはOr型です。

assert Int or Str == Or(Int, Str)
assert Int and Marker == And(Int, Marker)

Diff, Complement型は必ず簡約できるので真の代数演算型ではありません。