ctrs/
lib.rs

1//! ## or, an exploration of category theory for _systems programmers_
2//!
3//! ![a category](https://upload.wikimedia.org/wikipedia/commons/f/ff/Category_SVG.svg)
4//!
5//! What follows in this library is derived from _Category Theory for Programmers_, a long-running blog series by
6//! [Bartosz Milewki](https://twitter.com/BartoszMilewski). A nice "book" created from original blog posts can be found [here](https://github.com/hmemcpy/milewski-ctfp-pdf).
7//!
8//! #### Crate Health
9//!
10//! [![Build Status](https://travis-ci.org/damienstanton/ctrs.svg?branch=master)](https://travis-ci.org/damienstanton/ctrs)
11//!
12//! ### Goals
13//!
14//! My intention is simply to share my learning experience with category theory by using the built-in documentation and
15//! testing faculties that Rust provides. I will also conduct screen casts to explore each implementation so that I can
16//! make sure that what I commit to the crate is logical. I hope that by doing this, others can apply this knowledge to
17//! what they do at `$WORK` in C++, Go, Java, etc.
18//!
19//! ### Table of Contents
20//! | CTFP Chapter  | Topic | Articles | Lecture Videos | Notes |
21//! | -- | --- | --- | --- | --- |
22//! |    1    |   Introduction    |   [Category: The Essence of Composition](https://bartoszmilewski.com/2014/11/04/category-the-essence-of-composition/)      |   [Motivation](https://youtu.be/I8LbkfSSR58), [What is a category?](https://youtu.be/p54Hd7AmVFU)    |See [`id`](./fn.id.html) and [`compose`](./fn.compose.html)|
23//!
24//! ### Non-code challenge questions:
25//!
26//! Chapter 1
27//!
28//! _Is the world-wide web a category in any sense? Are links morphisms?_
29//!
30//! > I would say yes. We know that web pages have something akin to an identity morphism: its URI/URL. And links between pages
31//! may be composable (a link from site A to B can, through the redirect protocol, map to a third side C).
32//!
33//! Update: After a conversation with a few people in the #categorytheory channel on FP Slack, care must be
34//! taken to specify that we mean the morphism that defines the whole REST or HATEOAS command cycle for a link in this example; not the
35//! links themselves. So the correct answer to Bartosz's question depends on what we mean by what `links` are.
36//!
37//! _Is Facebook a category, with people as objects and friendships as morphisms?_
38//!
39//! > Not really, because social relationships cannot always compose. Friend C, friend of B, is not necessarily friend of A.
40//!
41//! _When is a directed graph a category?_
42//!
43//! > A DAG would classify as a category when a graph _G_ has vertices _V_ and edges _E_ such that:
44//! > - all paths in the graph can be concatenated
45//! > - each V has an E that loops back to itself (so that it satisfies identity)
46
47/// Identity is a unit under composition.
48///
49/// # Overview
50/// We describe a function over a generic type `T` that simply returns its parameterized value, unchanged. This might
51/// seem a little odd.
52///
53/// But as Bartosz describes, the motivation for understanding identity is to enable a higher order of composition:
54/// > You might be asking yourself the question: Why would anyone bother
55/// > with the identity function — a function that does nothing? Then again,
56/// > why do we bother with the number zero? Zero is a symbol for nothing.
57/// > Ancient Romans had a number system without a zero and they were
58/// > able to build excellent roads and aqueducts, some of which survive to
59/// > this day.
60/// > Neutral values like zero or id are extremely useful when working
61/// >
62/// > with symbolic variables. That’s why Romans were not very good at algebra, whereas the Arabs and the Persians, who were familiar with the
63/// > concept of zero, were. So the identity function becomes very handy as
64/// > an argument to, or a return from, a higher-order function. Higher order
65/// > functions are what make symbolic manipulation of functions possible.
66/// > They are the algebra of functions.
67/// >
68/// > To summarize: A category consists of objects and arrows (mor phisms). Arrows can be composed, and the composition is associative.
69/// >
70/// > Every object has an identity arrow that serves as a unit under composition.
71///
72/// # Example
73/// ```
74/// use ctrs::id;
75///
76/// let x = 1;
77/// assert_eq!(id(1), 1);
78///
79/// let y = "OK";
80/// assert_eq!(id(y), "OK");
81/// ```
82pub fn id<T>(x: T) -> T {
83    x
84}
85
86/// Composition is the heart of categorical computation.
87///
88/// # Overview
89/// Our definition of composition may appear confusing at first, but let's break it down. We start by defining generic
90/// types for our two input functions. These are`F` and `G`, respectively. These have a `'static` lifetime because we
91/// have to ensure that the borrow checker does not let these types out of scope before computation has finished. Next,
92/// we have types `Fv` and `Gv`, which represent the types for the return values for each of the functions F and G.
93/// Finally, we have our output type `V`, which is the result we want. We pass the functions F and G as parameters `f`
94/// and `g`.
95///
96/// Still with me?
97///
98/// Next, the return value is a `Box` of the generic `Fn` type that takes an Fv to a V. We have to _box_ the return
99/// value because we do not know how much size it could occupy on the stack (thus we allocate to the heap). Finally, we
100/// implement trait bounds on F and G, specifying how the chain should compose: F takes an Fv to a Gv, and then G takes a
101/// Gv to V.
102///
103/// Phew! 😅
104///
105/// Let's now see how this looks in practice using an example.
106///
107/// # Example
108/// ```
109/// use ctrs::{id, compose};
110///
111/// // Let's first define a trivial incrementer function.
112/// fn inc(x: i32) -> i32 {
113///   x + 1
114/// }
115///
116/// // and cover our bases by confirming inc works as expected.
117/// let x = 1;
118/// assert_eq!(inc(x), 2);
119///
120/// // Since we are composing functions on a given value, the syntax is
121/// // compose(A, B)(V). Knowing this, our passing test looks like:
122/// assert_eq!(compose(id, inc)(1), 2);
123/// ```
124///
125/// We can extend this idea! Let's take the situation where we've also defined an admittedly contrived `double`
126/// function, and want to compose its behavior with our existing incrementer. Mathematicians sometimes call the
127/// composition operator one might find in Haskell _after_, and understanding the way in which the function associates
128/// is indeed _g after f_.
129/// ```
130/// # use ctrs::{id, compose};
131/// # fn inc(x: i32) -> i32 {
132/// #   x + 1
133/// # }
134/// fn double(x: i32) -> i32 {
135///    x * 2
136/// }
137///
138/// let x = 1;
139/// assert_eq!(compose(inc, double)(1), 4);
140/// ```
141pub fn compose<F: 'static, G: 'static, Fv, Gv, V>(f: F, g: G) -> Box<Fn(Fv) -> V>
142where
143    F: Fn(Fv) -> Gv,
144    G: Fn(Gv) -> V,
145{
146    Box::new(move |x| g(f(x)))
147}