A Variant is a set of mutually exclusive cases to choose from.
/* loading */
The expression type animal = Dog | Cat | Bird
creates a
composed type animal
which consists of and three new types,
Dog
, Cat
and Bird
. The speak
function has the type
(pet: speakingAnimal): string
, so it takes a speakingAnimal
concrete type and it produces a string.
This is so common in ReasonML that there is some syntax sugar for
making a function that matches based on a single argument,
which is appropriately namd fun
:
/* loading */
If you want to know more about this syntax, see Single Argument Match Functions in the Reason docs.
Variants let you combine types like legos, snapping them together.
The Variants above are constructed with zero parameters; Dog
constructs a speakingAnimal
type without providing any additional
information.
It is also possible to declare Variants with take parameters, which allow for structured information to be conveyed in the type.
Imagine we wanted to capture contact information, and that we had a business rule that a person must have a primary contact and may have a secondary contact, and each contact method could be either verified or unverified, and valid contact types include email and phone. The following example lays out some types that can model this domain:
/* loading */
In this example, the contactInfo
variant has two type constructors.
Unlike the Dog
type constructor that didn't take any parameters,
each contactInfo
takes a single string as a parmeter: this means that
you can't construct an Email
or Phone
without providing a string.
The verifiable
variant takes a type and returns two types, one
which is Verified
, and one which is Unverified
for that passed type.
The verifiable
variant doesn't need to know anything about the types
it surrounds and conveys information for.
When we set up the user
record type, we declare that contact1
must
be a verifiableContactable
, which is a type alias for either a verified
or unverified email or phone.
By using the Single Argument Match Functions, it's easy to construct several render functions that can print all the combinations of users. Try adding some users above with different combinations, or changing the render format.
This example also features the option type, which is quite simple and heavily used. The option type represents either Some(something) or None. By representing an option this way, we can avoid three valued logic and know for sure whether something exists or not.
Variants can even point to themselves, to convey a tree-like structure:
/* loading */
Here are a few links to other sites that have discussed Variants in OCaml. Reminder: if you have reason-tools installed in Chrome, you can automatically convert between OCaml examples you see on the web and ReasonML.
enum
- WikipediaImage Credit: CN Cabin D in Toronto, ON in September 1979 by Marty Bernard on Flickr