category_theory

Module contains basic category concepts such as: composition, identity, unit, maybe, product, coproduct.

Types

Canonical implementation of a coproduct (sum type).

data Either a b = Left a | Right b

Examples

let check_positive = fn(x: Int) -> Either(Int, String) {
  case x >= 0 {
    True -> Left(x)
    False -> Right("negative number")
  }
}
check_positive(12)
// -> Left(12)
check_positive(-3)
// -> Right("negative number")
pub type Either(a, b) {
  Left(a)
  Right(b)
}

Constructors

  • Left(a)
  • Right(b)
pub type List(a) {
  Null
  Cons(List(a))
}

Constructors

  • Null
  • Cons(List(a))

Maybe type from Haskell (Option in gleam).

data Maybe = Nothing | Just a
-- Equivalent: Sum type between `unit` and `a`
type Maybe = Either () a

Examples

let safe_div = fn(a, b) {
  case b != 0.0 {
    True -> Just(a /. b)
    False -> Nothing
  }
}
safe_div(3.0, 4.0)
// -> Just(0,75)
safe_div(3.0, 0.0)
// -> Nothing
pub type Maybe(a) {
  Nothing
  Just(a)
}

Constructors

  • Nothing
  • Just(a)

Canonical implementation of a product (tuple). Examples

let even_to_string = fn(x: Int) -> Pair(String, Bool) {
  Pair(int.to_string(x), x % 2 == 0)
}
even_to_string(82).fst
// -> "82"
even_to_string(82).snd
// -> True
even_to_string(83).snd
// -> False
pub type Pair(a, b) {
  Pair(fst: a, snd: b)
}

Constructors

  • Pair(fst: a, snd: b)

A type corresponding to an empty set. It is not inhabited by any values.

pub type Void {
  Void(Void)
}

Constructors

  • Void(Void)

Functions

pub fn absurd(: Void) -> a

A function that can never be called. It is polymorphic in the return type.

pub fn compose(g: fn(a) -> b, f: fn(c) -> a) -> fn(c) -> b

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.

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(g . f) x = f (g x)

Properties of composition:

  • Associativity h . (g . f) == (h . g) . f == h . g . f
  • Identity see id for more info

Examples

let f = fn(x: Int) { int.to_string(x) }
let g = fn(s: String) { s == "28" }
let h = compose(g, f)
// -> h takes an int, transforms it into a string, then compares it to "28" and returns a bool
pub fn coproduct_factorizer(
  i: fn(a) -> b,
  j: fn(c) -> b,
) -> fn(Either(a, c)) -> b

Produces the factorizing function from a candidate c with two injections i and j to the best coproduct (either).
Property: i and j can be reconstructed from the canonical coproduct e
With m = coproduct_factorizer(i, j), we have:

  • i(x) = m(Left(x))
  • j(x) = m(Right(x))

Examples

// Given the candidate #(Int, Bool) with two injections from Int and Bool
let i = fn(x: Int) {#(x, False)}
let j = fn(x: Bool) {#(9, x)}
// We show that Either(Int, Bool) is a better coproduct by finding the mapping m:
let m = coproduct_factorizer(i, j)
m(Left(2))
// -> #(2, True)  
m(Right(False))
// -> #(9, False)  
pub fn id(x: a) -> a

The identity function is a unit of composition.

id :: a -> a
id a = a

It follows the identity conditions:

  • f . id == f
  • id . f == f

Examples

id(3)
// -> 3
id("abc")
// -> "abc"
pub fn main() -> Nil
pub fn maybe_compose(
  m1: fn(a) -> Maybe(b),
  m2: fn(b) -> Maybe(c),
) -> fn(a) -> Maybe(c)

Composition for the Maybe type

Examples

let safe_reciprocal = fn(x) {
  case x != 0.0 {
    True -> Just(1.0 /. x)
    False -> Nothing
  }
}
let safe_root = fn(x) {
  case x >=. 0.0 {
    True -> Just(x |> float.square_root() |> result.unwrap(0.0))
    False -> Nothing
  }
}
let safe_reciprocal_root = maybe_compose(safe_reciprocal, safe_root)
// -> a function that calculates sqrt(1/x)
safe_reciprocal_root(0.25)
// -> Just(2.0)
safe_reciprocal_root(0.0)
// -> Nothing
safe_reciprocal_root(-2.0)
// -> Nothing
pub fn maybe_id(x: a) -> Maybe(a)

The idenitity morphism for the Maybe type.

Examples

maybe_id(25)
// -> Just(25)
maybe_id(Nothing)
// -> Just(Nothing)
pub fn maybe_to_option(m: Maybe(a)) -> Option(a)

Converts from Maybe to gleam Option.

Examples

maybe_to_option(Nothing)
// -> None
maybe_to_option(Just(2))
// -> Some(2)
pub fn option_to_maybe(o: Option(a)) -> Maybe(a)

Converts from gleam Option to Maybe.

Examples

option_to_maybe(None)
// -> Nothing
option_to_maybe(Some(2))
// -> Just(2)
pub fn pair_to_tuple(p: Pair(a, b)) -> #(a, b)

Converts from Pair to gleam Tuple.

Examples

pair_to_tuple(Pair(2, True))
// -> #(2, True)
pub fn product_factorizer(
  p: fn(a) -> b,
  q: fn(a) -> c,
) -> fn(a) -> Pair(b, c)

Produces the factorizing function from a candidate c with two projections p and q to the best product (tuple / pair).
Property: p and q can be reconstructed from the canonical product
With m = product_factorizer(p, q), we have:

  • p(x) = m(x).fst
  • q(x) = m(x).snd

Examples

// Given the candidate Int with two projections to Int and Bool
let p = fn(x: Int) {x}
let q = fn(_: Int) {True}
// We show that Pair(Int, Bool) is a better product by finding the mapping m:
let m = product_factorizer(p, q)
m(7)
// -> Pair(7, True)  
pub fn tuple_to_pair(t: #(a, b)) -> Pair(a, b)

Converts from gleam Tuple to Pair.

Examples

tuple_to_pair(#(2, True))
// -> Pair(2, True)
pub fn unit(: a) -> Nil

A function from any type to a unit (Nil in gleam).

unit :: a -> ()
unit _ = ()

Examples

unit(42)
// -> Nil
unit(True)
// -> Nil
Search Document