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.