Current section
Files
Jump to
Current section
Files
src/category_theory.erl
-module(category_theory).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([id/1, compose/2, absurd/1, unit/1, product_factorizer/2, coproduct_factorizer/2, pair_to_tuple/1, tuple_to_pair/1, maybe_compose/2, maybe_id/1, maybe_to_option/1, option_to_maybe/1, main/0]).
-export_type([void/0, pair/2, either/2, 'maybe'/1, list_/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" Module contains basic category concepts such as: composition, identity, unit, maybe, product, coproduct.\n").
-type void() :: {void, void()}.
-type pair(EZK, EZL) :: {pair, EZK, EZL}.
-type either(EZM, EZN) :: {left, EZM} | {right, EZN}.
-type 'maybe'(EZO) :: nothing | {just, EZO}.
-type list_(EZP) :: null | {cons, list_(EZP)}.
-file("src/category_theory.gleam", 21).
?DOC(
" The `identity function` is a `unit of composition`.\n"
" ```haskell\n"
" id :: a -> a\n"
" id a = a\n"
" ```\n"
" It follows the identity conditions:\n"
" - f . id == f\n"
" - id . f == f\n"
" ### Examples\n"
" ```gleam\n"
" id(3)\n"
" // -> 3\n"
" id(\"abc\")\n"
" // -> \"abc\"\n"
" ```\n"
).
-spec id(EZQ) -> EZQ.
id(X) ->
X.
-file("src/category_theory.gleam", 40).
?DOC(
" Given a function `f` that takes an argument of type A and returns a B, and another function `g` that takes a B and returns a C, you can `compose` them by `passing the result of f to g`. \n"
" ```haskell\n"
" (.) :: (b -> c) -> (a -> b) -> (a -> c)\n"
" (g . f) x = f (g x)\n"
" ```\n"
" Properties of composition:\n"
" - Associativity h . (g . f) == (h . g) . f == h . g . f\n"
" - Identity see [`id`](#id) for more info\n"
" ### Examples\n"
" ```gleam\n"
" let f = fn(x: Int) { int.to_string(x) }\n"
" let g = fn(s: String) { s == \"28\" }\n"
" let h = compose(g, f)\n"
" // -> h takes an int, transforms it into a string, then compares it to \"28\" and returns a bool\n"
" ```\n"
).
-spec compose(fun((EZR) -> EZS), fun((EZT) -> EZR)) -> fun((EZT) -> EZS).
compose(G, F) ->
fun(X) -> G(F(X)) end.
-file("src/category_theory.gleam", 50).
?DOC(" A function that can `never` be called. It is polymorphic in the return type.\n").
-spec absurd(void()) -> any().
absurd(_) ->
erlang:error(#{gleam_error => panic,
message => <<"`panic` expression evaluated."/utf8>>,
module => <<"category_theory"/utf8>>,
function => <<"absurd"/utf8>>,
line => 51}).
-file("src/category_theory.gleam", 66).
?DOC(
" A function from any type to a unit (Nil in gleam).\n"
" ```haskell\n"
" unit :: a -> ()\n"
" unit _ = ()\n"
" ```\n"
" ### Examples\n"
" ```gleam\n"
" unit(42)\n"
" // -> Nil\n"
" unit(True)\n"
" // -> Nil\n"
" ```\n"
).
-spec unit(any()) -> nil.
unit(_) ->
nil.
-file("src/category_theory.gleam", 102).
?DOC(
" Produces the factorizing function from a `candidate` c with `two projections` p and q to the best product (tuple / pair). \\\n"
" Property: p and q can be `reconstructed` from the canonical product \\\n"
" With m = product_factorizer(p, q), we have:\n"
" - p(x) = m(x).fst\n"
" - q(x) = m(x).snd\n"
" ### Examples\n"
" ```gleam\n"
" // Given the candidate Int with two projections to Int and Bool\n"
" let p = fn(x: Int) {x}\n"
" let q = fn(_: Int) {True}\n"
" // We show that Pair(Int, Bool) is a better product by finding the mapping m:\n"
" let m = product_factorizer(p, q)\n"
" m(7)\n"
" // -> Pair(7, True) \n"
" ```\n"
).
-spec product_factorizer(fun((EZX) -> EZY), fun((EZX) -> EZZ)) -> fun((EZX) -> pair(EZY, EZZ)).
product_factorizer(P, Q) ->
fun(X) -> {pair, P(X), Q(X)} end.
-file("src/category_theory.gleam", 145).
?DOC(
" Produces the factorizing function from a `candidate` c with `two injections` i and j to the best coproduct (either). \\\n"
" Property: i and j can be `reconstructed` from the canonical coproduct e \\\n"
" With m = coproduct_factorizer(i, j), we have:\n"
" - i(x) = m(Left(x))\n"
" - j(x) = m(Right(x))\n"
" ### Examples\n"
" ```gleam\n"
" // Given the candidate #(Int, Bool) with two injections from Int and Bool\n"
" let i = fn(x: Int) {#(x, False)}\n"
" let j = fn(x: Bool) {#(9, x)}\n"
" // We show that Either(Int, Bool) is a better coproduct by finding the mapping m:\n"
" let m = coproduct_factorizer(i, j)\n"
" m(Left(2))\n"
" // -> #(2, True) \n"
" m(Right(False))\n"
" // -> #(9, False) \n"
" ```\n"
).
-spec coproduct_factorizer(fun((FAC) -> FAD), fun((FAE) -> FAD)) -> fun((either(FAC, FAE)) -> FAD).
coproduct_factorizer(I, J) ->
fun(E) -> case E of
{left, A} ->
I(A);
{right, B} ->
J(B)
end end.
-file("src/category_theory.gleam", 163).
?DOC(
" Converts from `Pair` to gleam `Tuple`.\n"
" ### Examples\n"
" ```gleam\n"
" pair_to_tuple(Pair(2, True))\n"
" // -> #(2, True)\n"
" ```\n"
).
-spec pair_to_tuple(pair(FAH, FAI)) -> {FAH, FAI}.
pair_to_tuple(P) ->
{erlang:element(2, P), erlang:element(3, P)}.
-file("src/category_theory.gleam", 173).
?DOC(
" Converts from gleam `Tuple` to `Pair`.\n"
" ### Examples\n"
" ```gleam\n"
" tuple_to_pair(#(2, True))\n"
" // -> Pair(2, True)\n"
" ```\n"
).
-spec tuple_to_pair({FAL, FAM}) -> pair(FAL, FAM).
tuple_to_pair(T) ->
{pair, erlang:element(1, T), erlang:element(2, T)}.
-file("src/category_theory.gleam", 225).
?DOC(
" `Composition` for the Maybe type \n"
" ### Examples\n"
" ```gleam\n"
" let safe_reciprocal = fn(x) {\n"
" case x != 0.0 {\n"
" True -> Just(1.0 /. x)\n"
" False -> Nothing\n"
" }\n"
" }\n"
" let safe_root = fn(x) {\n"
" case x >=. 0.0 {\n"
" True -> Just(x |> float.square_root() |> result.unwrap(0.0))\n"
" False -> Nothing\n"
" }\n"
" }\n"
" let safe_reciprocal_root = maybe_compose(safe_reciprocal, safe_root)\n"
" // -> a function that calculates sqrt(1/x)\n"
" safe_reciprocal_root(0.25)\n"
" // -> Just(2.0)\n"
" safe_reciprocal_root(0.0)\n"
" // -> Nothing\n"
" safe_reciprocal_root(-2.0)\n"
" // -> Nothing\n"
" ```\n"
).
-spec maybe_compose(fun((FAP) -> 'maybe'(FAQ)), fun((FAQ) -> 'maybe'(FAS))) -> fun((FAP) -> 'maybe'(FAS)).
maybe_compose(M1, M2) ->
fun(X) -> case M1(X) of
nothing ->
nothing;
{just, Y} ->
M2(Y)
end end.
-file("src/category_theory.gleam", 245).
?DOC(
" The `idenitity morphism` for the Maybe type.\n"
" ### Examples\n"
" ```gleam\n"
" maybe_id(25)\n"
" // -> Just(25)\n"
" maybe_id(Nothing)\n"
" // -> Just(Nothing)\n"
" ```\n"
).
-spec maybe_id(FAV) -> 'maybe'(FAV).
maybe_id(X) ->
{just, X}.
-file("src/category_theory.gleam", 257).
?DOC(
" Converts from `Maybe` to gleam `Option`.\n"
" ### Examples\n"
" ```gleam\n"
" maybe_to_option(Nothing)\n"
" // -> None\n"
" maybe_to_option(Just(2))\n"
" // -> Some(2)\n"
" ```\n"
).
-spec maybe_to_option('maybe'(FAX)) -> gleam@option:option(FAX).
maybe_to_option(M) ->
case M of
nothing ->
none;
{just, X} ->
{some, X}
end.
-file("src/category_theory.gleam", 272).
?DOC(
" Converts from gleam `Option` to `Maybe`.\n"
" ### Examples\n"
" ```gleam\n"
" option_to_maybe(None)\n"
" // -> Nothing\n"
" option_to_maybe(Some(2))\n"
" // -> Just(2)\n"
" ```\n"
).
-spec option_to_maybe(gleam@option:option(FBA)) -> 'maybe'(FBA).
option_to_maybe(O) ->
case O of
none ->
nothing;
{some, X} ->
{just, X}
end.
-file("src/category_theory.gleam", 286).
-spec main() -> nil.
main() ->
gleam_stdlib:println(<<"Category Theory!"/utf8>>).