代数演算型
代数演算型は、型を代数のようにみなして演算することで生成される型のことです。 代数演算型が扱う演算は、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 Str
とOption(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型、レコード型のor
やand
があります。
これらは簡約が可能なので真の代数演算型ではなく、型指定に使うと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型は必ず簡約できるので真の代数演算型ではありません。