It is possible to easily define complex data types using the type keyword.
# A Boolean is either True or False
type Bool:
True
FalseIf a constructor has any arguments, parentheses are necessary around it:
# An option either contains some value, or None
type Option:
Some { value }
NoneIf the data type has a single constructor, it can be destructured using open:
# A Box is a wrapper around a value.
type Boxed:
Box { value }
def main() -> _:
b = Boxed/Box(1)
open Boxed: b
return b.valueThe fields of the constructor that is being destructured with the match are bound to the matched variable plus . and the field names.
opt = Option/Some(1)
match opt:
case Option/Some:
return opt.value
case Option/None:
return 0Rules can also have patterns. They work like match expressions with explicit bindings:
(Option.map (Some value) f) = (Some (f value))
(Option.map None f) = NoneHowever, they also allow matching on multiple values at once, which is something that regular match can't do:
type Boolean:
True
False
(Option.is_both_some (Some lft_val) (Some rgt_val)) = True
(Option.is_both_some lft rgt) = FalseYou can read more about pattern matching rules in Pattern matching.
In conclusion, the type keyword is very useful as it allows you to easily create data types and deconstruct them.