Algebraic type
Algebraic types are types that are generated by operating types by treating them like algebra. Operations handled by them include Union, Intersection, Diff, Complement, and so on. Normal classes can only perform Union, and other operations will result in a type error.
Union
Union types can give multiple possibilities for types. As the name suggests, they are generated by the or
operator.
A typical Union is the Option
type. The Option
type is a T or NoneType
patch type, primarily representing values that may fail.
IntOrStr = Int or Str
assert dict.get("some key") in (Int or NoneType)
Option T = T or NoneType
Note that Union types are commutative but not associative. That is, X or Y or Z
is (X or Y) or Z
, not X or (Y or Z)
.
Allowing this would result in, for example, Int or Option(Str)
, Option(Int) or Str
and Option(Int or Str)
being of the same type.
Intersection
Intersection types are got by combining types with the and
operation.
Num = Add and Sub and Mul and Eq
As mentioned above, normal classes cannot be combined with the and
operation. This is because instances belong to only one class.
Diff
Diff types are got by not
operation.
It is better to use and not
as a closer notation to English text, but it is recommended to use just not
because it fits better alongside and
and or
.
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
Complement types is got by the not
operation, which is a unary operation. The not T
type is a shorthand for {=} not T
.
Intersection with type not T
is equivalent to Diff, and Diff with type not T
is equivalent to Intersection.
However, this way of writing is not recommended.
# the simplest definition of the non-zero number type
NonZero = Not {0}
# deprecated styles
{True} == Bool and not {False} # 1 == 2 + - 1
Bool == {True} not not {False} # 2 == 1 - -1
True Algebraic type
There are two algebraic types: apparent algebraic types that can be simplified and true algebraic types that cannot be further simplified.
The "apparent algebraic types" include or
and and
of Enum, Interval, and the Record types.
These are not true algebraic types because they are simplified, and using them as type specifiers will result in a Warning; to eliminate the Warning, you must either simplify them or define their types.
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}
True algebraic types include the types Or
and And
. Classes such as or
between classes are of type Or
.
assert Int or Str == Or(Int, Str)
assert Int and Marker == And(Int, Marker)
Diff, Complement types are not true algebraic types because they can always be simplified.