Skip to main content

Hi, I'm Mariano Guerra, below is my blog, if you want to learn more about me and what I do check a summary here: marianoguerra.github.io or find me on twitter @warianoguerra or Mastodon @marianoguerra@hachyderm.io

A tour through the beam ADT representation zoo

The Languages

Dynamically Typed

Statically Typed

Column meaning

Record Type

named set of fields (key, value pairs), also refered as types, structs, records etc

Union Type

like a record type but with more than one "shape", also refered as discriminated unions, variants etc

Type Dispatch

a function that will have different implementations according to the type of one (or more) of its arguments, also refered as protocols or multi methods

TL;DR Table

Language

Inspiration

Record Type

Union Type

Type Dispatch

Dynamic

Clojerl

Clojure

Yes

No

Yes

Efene

Python/JS

Yes*

No*

No

Elixir

Ruby

Yes

No*

Yes

Erlang

Prolog

Yes*

No*

No

LFE

Common Lisp

Yes*

No*

No

Static

Alpaca

ML

Yes

Yes

No*

Fez

F#

Yes

Yes

Yes

Gleam

ML/Rust

Yes

Yes

Not Yet?

Hamler

Purescript

Yes

Yes

Yes

PureErl

Purescript

Yes

Yes

Yes

Groups

Languages that compile record types to erlang records

Languages that compile record types to erlang maps

  • Alpaca: __struct__ field for records, no extra field for anonymous records

  • Clojerl: __type__ field

  • Elixir: __struct__ field for structs

  • Purerl: no extra field for anonymous records

  • Hamler : no extra field for anonymous records

Languages with union types

  • Alpaca: tagged tuple if it has values, atom if not

  • Gleam: tagged tuple if it has values, atom if not

  • Fez: tagged tuple if it has values, atom if not

  • Purerl: tagged tuple (not sure about variants with no values, should be like Hamler)

  • Hanler: tagged tuple even with variant with no values

Languages that do type dispatch

Notes

Alpaca

Records: "anonymous records".

Records are compiled as maps with the KV '__struct__' => 'record'. Because Alpaca doesn't provide any reflection facilities, more type information isn't propagated to the generated Core Erlang.

In the tag (in the case of variants/discriminated unions), it's just the atom representation of the tag name itself.

E.g. Some_tag 1 gets compiled to {'Some_tag', 1}

Alpaca's records get an extra key-value pair of '__struct__' to a rough description of its type/structure if the "structure" is flagged as a record.

Tagged Unions: (variants in OCaml) get compiled as an atom if there's no associated value, and as a tuple if there is.

Type Dispatch: Author says: "Not currently. This sort of thing might get handled by type classes but I haven't gone too far down that line of thinking yet"

Clojerl

Records: (deftype) compiled to Erlang maps with a special __type__ field.

Tagged Unions: No

Type Dispatch: defprotocol and deftype, extend-type, extend-protocol work as in Clojure.

Protocols are not reified as in Clojure, there are no runtime protocol objects.

Elixir

Records: structs are compiled to Erlang maps with a special __struct__ field.

Tagged Unions: No (usually ad-hoc tagged tuples are used for this)

Type Dispatch: Protocols are collected and consolidated at compile time

Gleam

Records: Compiled to Erlang records (hrl files are generated)

Tagged Unions: Compiled to tagged tuples, they are just gleam custom types with multiple "constructors", if a variant has no values it gets compiled to an atom

Type Dispatch: Not Yet? Will Gleam have type classes?

Fez

Records: Compiled to Erlang records

Tagged Unions: Compiled to tagged tuples

Type Dispatch: Class method calls

LFE, Efene and Erlang

LFE and Efene are just "dialects" of Erlang, that's why they are covered together here.

Records: Erlang records, which are compiled to a tuple where the first value is an atom with the name of the record: LFE Records, Efene Records, Erlang Records

Tagged Unions: Since they are dynamically typed they can use tagged tuples for this, there's no need to declare them, examples are functions that return {ok, V} or {error, Reason}.

Type Dispatch: No

PureErl

Records: Compiled to Erlang maps (without an extra field), really similar to alpaca "anonymous records"

Tagged Unions: Compiled to tagged tuples

Type Dispatch: Type Classes

There are also newtype

Hamler

Records: Compiled to Erlang maps (without an extra field)

Tagged Unions: Compiled to tagged tuples

Type Dispatch: Type Classes