Code for this post is available at 651548ffa8.

The builtin types are all well and good, but Erie isn’t much without a few additions: maps/dictionaries, structs, and especially alegbraic data types (ADT). Erie will eventually support all of these, but I focused on implementing ADTs first. I refer to them as “union” types throughout the compiler, but they are one in the same.

I want all Erie types to be declared with deftype, regardless of the ultimate shape of the type (i.e. ADT, struct, or type alias). By making the signature of deftype look like a function, it makes adding type parameters straight forward for supporting polymorphic types.

(deftype Maybe [a]
  (union [a 'nil]))

One big difference between Erie’s ADTs and those of other langauges that I’m familiar with is Erie doesn’t required “tags” for each option. For example, in Elm, representing Maybe looks like:

type Maybe a
  = Just a
  | Nothing

Note how the non-Nothing case requires the Just tag. This means a value of type String does not conform to the Maybe String type in Elm. In Erie, String will conform to (Maybe String) because of the lack of tags. I’m not aware (at least not yet) of why tags are necessary. I may run into the reason later in development, but for now, it seems to be working. If you, as a developer, like the tagged approach you can mimic it with tuples in the definition.

(deftype Result [error value]
  (union [{'ok value} {'error error}]))

Erie treats a quoted symbol as a type with a single value of itself. It allows for the above which will integrate nicely with Erlang and Elixir.

In the future I want deftype to be a macro that generates useful functions regarding that type. Specifically allowing matching in a case expression. For now deftype is treated as a special form by the compiler. As I continue to expand the functionality of macros, a large amount of that work should shift out of the compiler and into Erie macros.