It is possible to easily define complex data types using the type
keyword.
# A Boolean is either True or False
type Bool = True | False
If a constructor has any arguments, parentheses are necessary around it:
# An option either contains some value, or None
type Option = (Some val) | None
If the data type has a single constructor, it can be destructured using let
:
# A Box is a wrapper around a value.
type Boxed = (Box val)
let (Box value) = boxed; value
The fields of the constructor that is being destructured with the match
are bound to the matched variable plus .
and the field names.
Option.map = λoption λf
match option {
Some: (Some (f option.val))
None: None
}
Rules can also have patterns. They work like match expressions with explicit bindings:
(Option.map (Some value) f) = (Some (f value))
(Option.map None f) = None
However, 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) = False
You 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.