import TypeClass
defclass Witchcraft.Category do
@moduledoc """
A category is some collection of objects and relationships (morphisms) between them.
This idea is captured by the notion of an identity function for objects,
and the ability to compose relationships between objects. In most cases,
these are very straightforward, and composition and identity are the standard
functions from the `Quark` package or similar.
## Type Class
An instance of `Witchcraft.Category` must also implement `Witchcraft.Semigroupoid`,
and define `Witchcraft.Category.identity/1`.
Semigroupoid [compose/2, apply/2]
↓
Category [identity/1]
"""
alias __MODULE__
alias Witchcraft.Semigroupoid
extend Witchcraft.Semigroupoid
use Witchcraft.Internal, deps: [Witchcraft.Semigroupoid]
@type t :: any()
where do
@doc """
Take some value and return it again.
## Examples
iex> classic_id = identity(fn -> nil end)
...> classic_id.(42)
42
"""
@spec identity(Category.t()) :: Category.t()
def identity(category)
end
defalias id(category), as: :identity
properties do
def left_identity(data) do
a = generate(data)
ident = Semigroupoid.compose(Category.identity(a), a)
equal?(a, ident)
end
def right_identity(data) do
a = generate(data)
ident = Semigroupoid.compose(a, Category.identity(a))
equal?(a, ident)
end
end
end
definst Witchcraft.Category, for: Function do
def identity(_), do: &Quark.id/1
end