TypeClass v0.0.1 TypeClass.Class

Helpers for defining (bootstrapped) principled type classes

Generates a few modules and several functions and aliases. There is no need to use these internals directly, as the top-level API will suffice for actual productive use.

Example

defclass MyApp.Monoid do
  @extend MyApp.Semigroup

  @doc "Appends the identity to the monoid"
  @operator &&&
  @spec append_id(Monoid.t) :: Monoid.t
  def append_id(a), do: identity <> a

  where do
    @operator ^
    identity(any) :: any
  end

  defproperty reflexivity(a), do: a == a

  properties do
    def symmetry(a, b), do: equal?(a, b) == equal?(b, a)

    def transitivity(a, b, c) do
      equal?(a, b) && equal?(b, c) && equal?(a, c)
    end
  end
end

Structure

A Class is composed of several parts:

  • Dependancies
  • Protocol
  • Properties

Dependancies

Dependancies are the other type classes that the type class being defined extends. For istance, . It only needs the immediate parents in the chain, as those type classes will have performed all of the checks required for their parents.

Protocol

Class generates a Foo.Protocol submodule that holds all of the functions to be implemented. It’s a very lightweight/straightforward macro. The Protocol should never need to be called explicitly, as all of the functions will be aliased in the top-level API.

Properties

Being a (quasi-)principled type class also means having properties. Users must define at least one property, plus at least one sample data generator. These will be run at compile time (in dev and test environments), and will throw errors if they fail.

Summary

Macros

defclass(class_name, list)
run()
set_up()