Haex - Haskell As Elixir - Elixir Australia

Haskell has a rich type system with elegant and sophisticated ways of defining and working with data structures. Elixir has awesome things we all know and love, but less of that. How can we abuse macros and Elixir type specs to build a DSL that sort of gives us some of the same.

Haex is a proof of concept library I put together to see how far Elixir can be pushed to implement algebraic data types and other Haskell trappings.

Haex lets you do things like:

import Haex

data Maybe.t(a) :: Nothing | Just.t(a)

Maybe.just("cheese")
# {Maybe.Just, "cheese"}

Maybe.Just.new("cheese")
# {Maybe.Just, "cheese"}

Maybe.nothing()
# Maybe.Nothing

Maybe.Nothing.new()
# Maybe.Nothing

From the README:

“Haskell as Elixir” - A DSL for implementing Haskell style sum and product data types in Elixir

(pronounced “hacks”)

A succinct statement generates a number of modules, and helper functions, along with valid dialyzer type and specs to work with those data structures.

The goal is to make it quicker and easier to work with rich types without having to implement a lot of boilerplate code to build common patterns. This is particularly true in the case of Elixir structs, which to be used properly, require a defstruct call, @type declaration (which is almost but not quite identical), and an @enforce_keys annotation. All of these can be automated away.

A secondary goal is to encourage good use of types that are understand by dialyzer. This makes it easier to work with and reason about the code, and aids documentation of what functions expect and return.

There’s an overview from Elixir Australia December 2020 meetup, and Haex is available on GitHub at madlep/haex