Syntax & Examples
Importing
The algebraic data type can be defined using @data
macro. It can be imported from the Moshi.Data
module:
The Moshi.Data
module also defines a set of reflection functions to work with the algebraic data types. You can check Reflection for more information. All the name can be imported together using:
Quick Example
Here is a quick example of defining a simple algebraic data type:
This defines a new algebraic data type Message
with 4 variants: Quit
, Move
, Write
, and ChangeColor
. The Move
variant has two fields x
and y
of type Int
. The Write
variant has a single field of type String
. The ChangeColor
variant has three fields of type Int
.
You can create an instance of the Message
type as follows:
Formal Syntax
The syntax is as follows:
<data>
is the top-level syntax for defining an algebraic data type. It starts with the @data
macro followed by the name of the data type. Optionally, it can have a supertype. The supertype can be any type that the data type extends. The begin
keyword is used to start the body of the data type. The body consists of one or more variants.
A <variant>
can be one of three types: <singleton>
, <anonymous>
, or <named>
. A <singleton>
variant is a variant with no fields. An <anonymous>
variant is a variant with anonymous fields. A <named>
variant is a variant with named fields.
Singleton Variant
The singleton variant is like an Base.@enum
variant. It can be defined directly as:
Unlike Base.@enum
and rust enum
, the singleton variant instance must be constructed explicitly with an empty constructor:
Anonymous Variant
The anonymous variant is useful when you want to define a variant with anonymous fields. It can be defined as:
for example, the Write
and ChangeColor
variants in the above example are anonymous variants.
Named Variant
The named variant is just like normal Julia struct definition, except that it is defined inside the data type. It can be defined as:
for example, the Move
variant in the above example is a named variant.
Generics/Type Parameters
The @data
macro also supports defining algebraic data types with type parameters. For example:
This defines a new algebraic data type Option
with two variants: Some
and None
. The Some
variant has a single field of type T
. The None
variant has no fields.
The type parameters should be declared in the type definition
the syntax is the same as a normal struct
type parameter declaration. Inside the begin ... end
body,
the type parameters can be used as normal types.
Default Pattern
The ADT defined with Moshi supports a default pattern when doing pattern matching.
This is always the inverse operation of the generated constructor. Taking the Message
example above:
the call pattern here does not need to match the exactly same number of arguments as the constructor.
Intead if the pattern is Move(x)
it is equivalent to Move(x, _)
.
For named variants, because it generates a @kwdef
like constructor, the following keyword argument
pattern is also supported: