├── .gitignore ├── Makefile ├── README.md ├── _static ├── css │ └── style.css ├── fonts │ └── Inconsolata.otf └── style.css ├── conf.py ├── docs └── reading-group │ ├── .gitignore │ └── part-1 │ ├── chapter-00 │ └── challenges │ │ └── rust │ │ └── solution.rs │ ├── chapter-01 │ ├── 00-category-the-essence-of-computation.org │ └── challenges │ │ ├── answers.rst │ │ └── python │ │ └── solution.py │ ├── chapter-02 │ ├── 01-types-and-functions.org │ └── challenges │ │ ├── answers.rst │ │ ├── c++ │ │ ├── makefile │ │ └── solution.cpp │ │ └── python │ │ └── solution.py │ ├── chapter-03 │ └── 03-categories-great-and-small.md │ └── chapter-04 │ └── 04-kleisli-categories.md ├── latest ├── CategoriesforProgrammers.epub ├── CategoriesforProgrammers.pdf └── create_pdf.sh ├── make.bat ├── src ├── images │ ├── 2014 │ │ ├── 10 │ │ │ ├── img_1299.jpg │ │ │ ├── img_1329.jpg │ │ │ └── img_1330.jpg │ │ └── 12 │ │ │ ├── coproductpattern.jpg │ │ │ ├── coproductranking.jpg │ │ │ ├── final.jpg │ │ │ ├── initial.jpg │ │ │ ├── monoid.jpg │ │ │ ├── monoidhomset.jpg │ │ │ ├── piggyback.jpg │ │ │ ├── productcandidates.jpg │ │ │ ├── productpattern.jpg │ │ │ ├── productranking.jpg │ │ │ └── uniqueness.jpg │ ├── 2015 │ │ ├── 11 │ │ │ └── sheets.png │ │ ├── 01 │ │ │ ├── bifunctor.jpg │ │ │ ├── bimap.jpg │ │ │ ├── contravariant.jpg │ │ │ ├── dimap.jpg │ │ │ ├── first.jpg │ │ │ ├── functor.jpg │ │ │ ├── functorcompos.jpg │ │ │ ├── functorid.jpg │ │ │ ├── functormaybe.jpg │ │ │ ├── not-a-product.jpg │ │ │ ├── pair.jpg │ │ │ └── second.jpg │ │ ├── 03 │ │ │ ├── functionpattern.jpg │ │ │ ├── functionranking.jpg │ │ │ ├── functionset.jpg │ │ │ ├── hom-set.jpg │ │ │ ├── set-hom-set.jpg │ │ │ └── universalfunctionobject.jpg │ │ ├── 04 │ │ │ ├── 10_horizontal.jpg │ │ │ ├── 1_functors.jpg │ │ │ ├── 2_natcomp.jpg │ │ │ ├── 3_naturality.jpg │ │ │ ├── 4_transport.jpg │ │ │ ├── 5_vertical.jpg │ │ │ ├── 6_verticalnaturality.jpg │ │ │ ├── 6a_vertical.jpg │ │ │ ├── 7_cathomset.jpg │ │ │ ├── 8_cat-2-cat.jpg │ │ │ ├── 9_horizontal.jpg │ │ │ ├── asteroids.png │ │ │ ├── classes.jpg │ │ │ ├── colimit.jpg │ │ │ ├── cone.jpg │ │ │ ├── conecommutativity.jpg │ │ │ ├── conenaturality.jpg │ │ │ ├── continuity.jpg │ │ │ ├── equalizercone.jpg │ │ │ ├── equilizerlimit.jpg │ │ │ ├── feynman.jpg │ │ │ ├── homsetmapping.jpg │ │ │ ├── mortar.jpg │ │ │ ├── natmapping.jpg │ │ │ ├── naturality.jpg │ │ │ ├── productcone.jpg │ │ │ ├── pullbackcone.jpg │ │ │ ├── pullbacklimit.jpg │ │ │ ├── sideways.jpg │ │ │ ├── snell.jpg │ │ │ ├── two.jpg │ │ │ └── twodelta.jpg │ │ ├── 07 │ │ │ ├── bunnies.jpg │ │ │ ├── hom-functor.jpg │ │ │ ├── hom-set.jpg │ │ │ ├── monoid-pattern.jpg │ │ │ ├── monoid-ranking.jpg │ │ │ ├── yoneda-embedding-2.jpg │ │ │ └── yoneda-embedding.jpg │ │ ├── 08 │ │ │ ├── yoneda1-e1440290035365.png │ │ │ ├── yoneda1.png │ │ │ └── yoneda2.png │ │ └── 09 │ │ │ ├── yoneda3.png │ │ │ ├── yoneda4.png │ │ │ └── yoneda5.png │ ├── 2016 │ │ ├── 12 │ │ │ ├── assoc.png │ │ │ ├── assoc1.png │ │ │ ├── assoc2.png │ │ │ ├── assocmon.png │ │ │ ├── assoctensor.jpg │ │ │ ├── exptree.png │ │ │ ├── horizcomp.png │ │ │ ├── monoid-1.jpg │ │ │ ├── unitlawcomp-1.png │ │ │ ├── unitlawcomp.png │ │ │ └── unitmon.jpg │ │ ├── 04 │ │ │ ├── adj-1.jpg │ │ │ ├── adj-counit.jpg │ │ │ ├── adj-expo.jpg │ │ │ ├── adj-homsets.jpg │ │ │ ├── adj-product.jpg │ │ │ ├── adj-productcat.jpg │ │ │ └── adj-unit.jpg │ │ └── 05 │ │ │ ├── forgetful.jpg │ │ │ ├── forgettingmorphisms.jpg │ │ │ ├── freeimage.jpg │ │ │ └── freemonadjunction.jpg │ └── 2017 │ │ ├── 02 │ │ ├── alg.png │ │ ├── alg2.png │ │ ├── alg3.png │ │ ├── alg3a.png │ │ ├── alg4.png │ │ ├── alg5.png │ │ ├── alg6.png │ │ ├── alg7.png │ │ ├── triangles-2.png │ │ └── triangles.png │ │ ├── 03 │ │ ├── end-1.jpg │ │ ├── end-2.jpg │ │ ├── end-21.jpg │ │ ├── end-31.jpg │ │ ├── end.jpg │ │ ├── end1.jpg │ │ ├── pigalg.png │ │ ├── talg1.png │ │ ├── talg2.png │ │ ├── talg31.png │ │ ├── talg4.png │ │ └── talg5.png │ │ ├── 04 │ │ ├── kan10a.jpg │ │ ├── kan10b.jpg │ │ ├── kan112.jpg │ │ ├── kan12.jpg │ │ ├── kan13.jpg │ │ ├── kan14.jpg │ │ ├── kan15.jpg │ │ ├── kan2.jpg │ │ ├── kan3-e1492120491591.jpg │ │ ├── kan31-e1492120512209.jpg │ │ ├── kan5.jpg │ │ ├── kan6.jpg │ │ ├── kan7.jpg │ │ ├── kan81.jpg │ │ └── kan92.jpg │ │ ├── 05 │ │ ├── assoc.jpg │ │ ├── compcoherence.jpg │ │ ├── composition.jpg │ │ ├── functorcomp.jpg │ │ ├── functorid.jpg │ │ ├── id.jpg │ │ ├── idcoherence.jpg │ │ ├── leftid.jpg │ │ └── rightid.jpg │ │ ├── 07 │ │ ├── monomorphism.jpg │ │ ├── notmono.jpg │ │ ├── pullback.jpg │ │ ├── subsetinjection.jpg │ │ └── true.jpg │ │ ├── 08 │ │ ├── equalize1.png │ │ ├── equalize2.png │ │ ├── lawvere1.png │ │ ├── liftl.png │ │ └── liftpower.png │ │ └── 09 │ │ ├── bicat.png │ │ ├── bimonad.png │ │ ├── compspan.png │ │ ├── monad.png │ │ ├── morphspan.png │ │ ├── pullspan.png │ │ ├── span.png │ │ ├── spanmonad.png │ │ ├── spanmul.png │ │ ├── spanunit.png │ │ └── twocat.png ├── index.rst ├── part1 │ ├── 01-category-the-essence-of-computing.rst │ ├── 02-types-and-functions.rst │ ├── 03-categories-great-and-small.rst │ ├── 04-kleisli-categories.rst │ ├── 05-products-and-coproducts.rst │ ├── 06-simple-algebraic-data-types.rst │ ├── 07-functors.rst │ ├── 08-functorality.rst │ ├── 09-function-types.rst │ └── 10-natural-transformations.rst ├── part2 │ ├── 11-declarative-programming.rst │ ├── 12-limits-and-colimits.rst │ ├── 13-free-monoids.rst │ ├── 14-representable-functors.rst │ ├── 15-the-yoneda-lemma.rst │ └── 16-yoneda-embedding.rst ├── part3 │ ├── 17-its-all-about-morphisms.rst │ ├── 18-adjunctions.rst │ ├── 19-free-forgetful-adjunctions.rst │ ├── 20-monads-programmers-definition.rst │ ├── 21-monads-and-effects.rst │ ├── 22-monads-categorically.rst │ ├── 23-comonads.rst │ ├── 24-f-algebra.rst │ ├── 25-algebras-for-monads.rst │ ├── 26-end-and-coends.rst │ ├── 27-kan-extensions.rst │ ├── 28-enriched-categories.rst │ ├── 29-topoi.rst │ ├── 30-lawvere-theories.rst │ └── 31-monads-monoids-and-categories.rst └── preface.rst └── tools ├── README.md └── get_images.py /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | .DS_Store -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = CategoriesforProgrammers 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Categories for Programmers 2 | 3 | This is a [Sphinx build](http://www.sphinx-doc.org/) for Bartosz 4 | Milewski's 5 | [excellent series of blog posts "Category Theory for Programmers"](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/). 6 | My main goal is to create an EPUB version of the series that is easy to consume 7 | on e-readers. 8 | 9 | ## Just want to read the book? 10 | 11 | The most recent build of the book is in the `latest` directory. You 12 | can 13 | [download it with this link](https://github.com/abingham/categories-for-programmers/raw/master/latest/CategoriesforProgrammers.epub). 14 | 15 | 16 | ## Building the EPUB 17 | 18 | The main tool you need for building the output 19 | is [Sphinx](http://www.sphinx-doc.org/). The Sphinx website does a fine job 20 | explaining how to install it, so I won't go into any detail here. On linux or OS 21 | X you'll also need to install `make`. 22 | 23 | Once Sphinx is installed, open a terminal and go to the directory containing 24 | this file. Once in that directory run: 25 | 26 | ``` 27 | make epub 28 | ``` 29 | 30 | This should work on OS X, linux, and windows. 31 | 32 | Once this is done, the output will be in `_build/epub`. 33 | 34 | ## Contributing 35 | 36 | At this point the bulk of the conversion work is done. There are some open 37 | issues in the tracker that you could look at. Or basic editorial work would 38 | probably be useful as well. 39 | -------------------------------------------------------------------------------- /_static/css/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: Inconsolata; 3 | font-weight: normal; 4 | font-style: normal; 5 | src: url("../fonts/Inconsolata.otf") format("opentype"); 6 | } 7 | 8 | .header{ 9 | font-style: italic; 10 | } 11 | 12 | .image-box { 13 | display: inline-block; 14 | } 15 | .image-box img{ 16 | 17 | } 18 | .image-box p{ 19 | font-style:italic; 20 | } 21 | pre, samp, code, 22 | .source{ 23 | font-family: "Inconsolata"; 24 | } 25 | 26 | .box{ 27 | background-color: lightgrey; 28 | } 29 | -------------------------------------------------------------------------------- /_static/fonts/Inconsolata.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/_static/fonts/Inconsolata.otf -------------------------------------------------------------------------------- /_static/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: FiraMono; 3 | font-weight: normal; 4 | font-style: normal; 5 | src: url("../fonts/FiraMono-Regular.otf") format("opentype");} 6 | 7 | .header{ 8 | font-style: italic; 9 | } 10 | 11 | .image-box { 12 | display: inline-block; 13 | } 14 | .image-box img{ 15 | 16 | } 17 | .image-box p{ 18 | font-style:italic; 19 | } 20 | pre, samp, code, 21 | .source{ 22 | font-family: "FiraMono"; 23 | } 24 | 25 | .box{ 26 | background-color: lightgrey; 27 | } 28 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Categories for Programmers documentation build configuration file, created by 5 | # sphinx-quickstart on Sun Sep 3 19:50:50 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | # import sys 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | # 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | # The suffix(es) of source filenames. 40 | # You can specify multiple suffix as a list of string: 41 | # 42 | # source_suffix = ['.rst', '.md'] 43 | source_suffix = '.rst' 44 | 45 | # The master toctree document. 46 | master_doc = 'src/index' 47 | 48 | # General information about the project. 49 | project = 'Categories for Programmers' 50 | copyright = '2017, Bartosz Milewski' 51 | author = 'Bartosz Milewski' 52 | 53 | # The version info for the project you're documenting, acts as replacement for 54 | # |version| and |release|, also used in various other places throughout the 55 | # built documents. 56 | # 57 | # The short X.Y version. 58 | version = '1.0.0' 59 | # The full version, including alpha/beta/rc tags. 60 | release = '' 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | # 65 | # This is also used if you do content translation via gettext catalogs. 66 | # Usually you set "language" from the command line for these cases. 67 | language = None 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | # This patterns also effect to html_static_path and html_extra_path 72 | exclude_patterns = ['docs', '_build', 'Thumbs.db', '.DS_Store'] 73 | 74 | # The name of the Pygments (syntax highlighting) style to use. 75 | pygments_style = 'sphinx' 76 | 77 | # If true, `todo` and `todoList` produce output, else they produce nothing. 78 | todo_include_todos = False 79 | 80 | 81 | # -- Options for HTML output ---------------------------------------------- 82 | 83 | # The theme to use for HTML and HTML Help pages. See the documentation for 84 | # a list of builtin themes. 85 | # 86 | html_theme = 'alabaster' 87 | 88 | # Theme options are theme-specific and customize the look and feel of a theme 89 | # further. For a list of options available for each theme, see the 90 | # documentation. 91 | # 92 | # html_theme_options = {} 93 | 94 | # Add any paths that contain custom static files (such as style sheets) here, 95 | # relative to this directory. They are copied after the builtin static files, 96 | # so a file named "default.css" will overwrite the builtin "default.css". 97 | html_static_path = ['_static'] 98 | 99 | 100 | # -- Options for HTMLHelp output ------------------------------------------ 101 | 102 | # Output file base name for HTML help builder. 103 | htmlhelp_basename = 'CategoriesforProgrammersdoc' 104 | 105 | 106 | # -- Options for LaTeX output --------------------------------------------- 107 | 108 | latex_elements = { 109 | # The paper size ('letterpaper' or 'a4paper'). 110 | # 111 | # 'papersize': 'letterpaper', 112 | 113 | # The font size ('10pt', '11pt' or '12pt'). 114 | # 115 | # 'pointsize': '10pt', 116 | 117 | # Additional stuff for the LaTeX preamble. 118 | # 119 | # 'preamble': '', 120 | 121 | # Latex figure (float) alignment 122 | # 123 | # 'figure_align': 'htbp', 124 | } 125 | 126 | # Grouping the document tree into LaTeX files. List of tuples 127 | # (source start file, target name, title, 128 | # author, documentclass [howto, manual, or own class]). 129 | latex_documents = [ 130 | (master_doc, 'CategoriesforProgrammers.tex', 'Categories for Programmers Documentation', 131 | 'Bartosz Milewski', 'manual'), 132 | ] 133 | 134 | 135 | # -- Options for manual page output --------------------------------------- 136 | 137 | # One entry per manual page. List of tuples 138 | # (source start file, name, description, authors, manual section). 139 | man_pages = [ 140 | (master_doc, 'categoriesforprogrammers', 'Categories for Programmers Documentation', 141 | [author], 1) 142 | ] 143 | 144 | 145 | # -- Options for Texinfo output ------------------------------------------- 146 | 147 | # Grouping the document tree into Texinfo files. List of tuples 148 | # (source start file, target name, title, author, 149 | # dir menu entry, description, category) 150 | texinfo_documents = [ 151 | (master_doc, 'CategoriesforProgrammers', 'Categories for Programmers Documentation', 152 | author, 'CategoriesforProgrammers', 'One line description of project.', 153 | 'Miscellaneous'), 154 | ] 155 | 156 | 157 | 158 | # -- Options for Epub output ---------------------------------------------- 159 | 160 | # Bibliographic Dublin Core info. 161 | epub_title = project 162 | epub_author = author 163 | epub_publisher = author 164 | epub_copyright = copyright 165 | 166 | # The unique identifier of the text. This can be a ISBN number 167 | # or the project homepage. 168 | # 169 | # epub_identifier = '' 170 | 171 | # A unique identification for the text. 172 | # 173 | # epub_uid = '' 174 | 175 | # A list of files that should not be packed into the epub file. 176 | epub_exclude_files = ['search.html'] 177 | 178 | 179 | def setup(app): 180 | app.add_stylesheet('css/style.css') # may also be an URL 181 | -------------------------------------------------------------------------------- /docs/reading-group/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-00/challenges/rust/solution.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "lib"] 2 | #![allow(dead_code)] 3 | #![feature(conservative_impl_trait)] 4 | #![feature(try_from)] 5 | 6 | /// 1. Implement, as best as you can, the identity function in your favorite 7 | /// language (or the second favorite, if your favorite language happens to be 8 | /// Haskell). 9 | fn identity(x: T) -> T { 10 | x 11 | } 12 | 13 | /// 2. Implement the composition function in your favorite language. 14 | /// It takes two functions as arguments and returns a function that 15 | /// is their composition. 16 | fn compose(f: F, g: G) -> impl Fn(A) -> C 17 | where 18 | F: Fn(A) -> B, 19 | G: Fn(B) -> C, 20 | { 21 | move |x| g(f(x)) 22 | } 23 | 24 | /// 3. Write a program that tries to test that your composition function 25 | /// respects identity. 26 | fn test_identity_under_composition() { 27 | let chr = >::try_from; 28 | 29 | assert_eq!(compose(identity, chr)(123), chr(123)); 30 | assert_eq!(compose(chr, identity)(456), chr(456)); 31 | } 32 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-01/00-category-the-essence-of-computation.org: -------------------------------------------------------------------------------- 1 | * Categories <=> Composition 2 | 3 | Transitivity: *If* a->b *and* b->c *then* a->c 4 | 5 | Arrows are *morphisms*. 6 | 7 | Example: 8 | - morphisms are functions 9 | - objects are types. 10 | 11 | #+BEGIN_SRC haskell 12 | f :: A -> B 13 | g :: B -> C 14 | h = g.f 15 | #+END_SRC 16 | 17 | * Property 1: Associative 18 | 19 | "you don't need parentheses to compose them" 20 | 21 | #+BEGIN_SRC 22 | h (g f) = (h g) f = h g f 23 | #+END_SRC 24 | 25 | * Property 2: Unit of composition 26 | 27 | "This arrow loops from the object to itself" 28 | 29 | #+BEGIN_SRC 30 | f idA = f 31 | idB f = f 32 | #+END_SRC 33 | 34 | In Haskell: 35 | 36 | #+BEGIN_SRC haskell 37 | id :: a -> a 38 | id x = x 39 | #+END_SRC 40 | 41 | * Why categories and functional programming? 42 | 43 | * Elegance 44 | 45 | "We often describe some piece of code as 46 | elegant or beautiful, but what we really 47 | mean is that it’s easy to process by our 48 | limited human minds." 49 | 50 | * Surface area metaphor, part 1 51 | 52 | "So what are the right chunks for the 53 | composition of programs? Their surface 54 | area has to increase slower than their 55 | volume...The surface area is the 56 | information we need in order to compose 57 | chunks." 58 | 59 | * Surface area metaphor, part 2 60 | 61 | "The moment you have to dig into the 62 | implementation of the object in order to 63 | understand how to compose it with other 64 | objects, you’ve lost the advantages of 65 | your programming paradigm." 66 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-01/challenges/answers.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Questions 3 | =========== 4 | 5 | 4. Is the world-wide web a category in any sense? Are links morphisms? 6 | ====================================================================== 7 | 8 | If you think of links as morphisms and pages as objects, then one first 9 | approximation the web is a category. 10 | 11 | 5. Is Facebook a category, with people as objects and friendships as morphisms? 12 | =============================================================================== 13 | 14 | We think not. You can't always reach your friends' friends. 15 | 16 | 6. When is a directed graph a category? 17 | ======================================= 18 | 19 | It needs cycles to return to self (identity). Reflexive! 20 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-01/challenges/python/solution.py: -------------------------------------------------------------------------------- 1 | def identity(x): 2 | """1. Implement, as best as you can, the identity function in your favorite 3 | language (or the second favorite, if your favorite language happens to be 4 | Haskell). 5 | """ 6 | return x 7 | 8 | 9 | def compose(f, g): 10 | """2. Implement the composition function in your favorite language. It takes 11 | two functions as arguments and returns a function that is their 12 | composition. 13 | """ 14 | return lambda x: g(f(x)) 15 | 16 | 17 | def test_identity_under_composition(): 18 | """3. Write a program that tries to test that your composition function 19 | respects identity. 20 | """ 21 | assert compose(chr, identity)(123) == chr(123) 22 | assert compose(identity, chr)(456) == chr(456) 23 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-02/01-types-and-functions.org: -------------------------------------------------------------------------------- 1 | * Static vs. dynamic typing 2 | 3 | I think it's safe to leave this argument 4 | aside for now. We're talking about 5 | static typing and compilers in this 6 | book! 7 | 8 | But I like this quote: 9 | 10 | "A better criterion would be to measure 11 | how many projects fall behind schedule 12 | or are delivered with drastically 13 | reduced functionality." 14 | 15 | * Types are sets 16 | 17 | - Bool = {True, False} 18 | - Char = {'a', 'b', 'c', ...} 19 | - String = { ... all possible strings ...} 20 | 21 | * The category called *Set* 22 | 23 | We'll be working with *Set*: 24 | 25 | - objects are sets (types!) 26 | - morphisms are functions 27 | 28 | "*Set* is a very special category, 29 | because we can actually peek inside its 30 | objects and get a lot of intuitions from 31 | doing that." 32 | 33 | * _|_: Brilliant idea or major hack 34 | 35 | _|_ (a.k.a. *bottom*) corresponds to a 36 | *non-terminating computation*, and all 37 | types in Haskell include it. 38 | 39 | * Haskell and bottom 40 | 41 | Haskell needs to execute code, and hence 42 | is subject to the halting problem. 43 | 44 | *Hask* vs. *Set* 45 | 46 | "Functions that may return bottom are 47 | called *partial*, as opposed to *total* 48 | functions, which return valid results 49 | for every possible argument." 50 | 51 | #+BEGIN_SRC haskell 52 | f :: Bool -> Bool 53 | f = undefined 54 | #+END_SRC 55 | 56 | * Mathematical models 57 | 58 | It would be nice to be able to prove 59 | things about the semantics of our 60 | programs. 61 | 62 | * Operational semantics 63 | 64 | Based on the idea of a formalized, 65 | idealized interpreter. 66 | 67 | Very difficult to prove 68 | things...programs have to be "executed" 69 | on the machine. 70 | 71 | * Denoatational semantics 72 | 73 | Each programming construct is given a 74 | mathematical interpretation. 75 | 76 | To prove qualities of a program, you 77 | prove (generally relatively simple) 78 | mathematical theorems. 79 | 80 | * But... 81 | 82 | "What’s the mathematical model for 83 | reading a character from the keyboard or 84 | sending a packet across the network?" 85 | 86 | Eugenio Moggi (Univ. of Genoa) showed 87 | that computational effect can be mapped 88 | to monads. 89 | 90 | More on monads later in the book... 91 | 92 | * Pure vs. dirty functions 93 | 94 | "In programming languages, functions 95 | that always produce the same result 96 | given the same input and have no side 97 | effects are called *pure functions*." 98 | 99 | Functions are pure in Haskell. Not so 100 | much in C++. 101 | 102 | Monads let us model side-effects in 103 | purely functional languages. 104 | 105 | * Interesting types 106 | 107 | * Void 108 | 109 | Type with no values. *Not the same as 110 | void in C/C++.* 111 | 112 | Makes functions uncallable but 113 | type-checkable. 114 | 115 | #+BEGIN_SRC haskell 116 | absurd :: Void -> a 117 | #+END_SRC 118 | 119 | *ex falso sequitur quodlibet* 120 | 121 | * () / void 122 | 123 | A type with a single value. 124 | 125 | () is also called "unit" in Haskell. 126 | 127 | * Parametric polymorphism 128 | 129 | Lower-case type specifiers in Haskell 130 | mean "any type". 131 | 132 | #+BEGIN_SRC haskell 133 | unit :: a -> () 134 | unit _ = () 135 | #+END_SRC 136 | 137 | Compare to upper-case type specifiers 138 | which are concrete. 139 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-02/challenges/answers.rst: -------------------------------------------------------------------------------- 1 | 5. How many different functions are there from ``Bool`` to ``Bool``? Can 2 | you implement them all? 3 | 4 | const true, const false, invert, id 5 | 6 | 6. Draw a picture of a category whose only objects are the types 7 | ``Void``, ``()`` (unit), and ``Bool``; with arrows corresponding to 8 | all possible functions between these types. Label the arrows with the 9 | names of the functions. 10 | 11 | Void -> Void 12 | () -> () 13 | Bool -> Bool (4) 14 | Bool -> () 15 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-02/challenges/c++/makefile: -------------------------------------------------------------------------------- 1 | all: solution.cpp 2 | c++ -std=c++11 solution.cpp 3 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-02/challenges/c++/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // 4. Which of these C++ functions are pure? Try to memoize them and 7 | // observe what happens when you call them multiple times: memoized and 8 | // not. 9 | 10 | // 1. The factorial function from the example in the text. 11 | // 2. .. code-block:: c++ 12 | 13 | // std::getchar() 14 | 15 | // 3. .. code-block:: c++ 16 | 17 | // bool f() { 18 | // std::cout << "Hello!" << std::endl; 19 | // return true; 20 | // } 21 | 22 | // 4. .. code-block:: c++ 23 | 24 | // int f(int x) 25 | // { 26 | // static int y = 0; 27 | // y += x; 28 | // return y; 29 | // } 30 | 31 | // A: None are pure! All behave differently under memoization. 32 | 33 | template 34 | class Memoize { 35 | public: 36 | Memoize(std::function func) : 37 | func_(func) 38 | {} 39 | 40 | Rslt operator()(Arg arg) { 41 | auto i = results_.find(arg);; 42 | if (i == results_.end()) { 43 | auto rslt = func_(arg); 44 | results_.insert(std::make_pair(arg, rslt)); 45 | return rslt; 46 | } 47 | else { 48 | return i->second; 49 | } 50 | } 51 | 52 | private: 53 | std::function func_; 54 | std::map results_; 55 | }; 56 | 57 | template 58 | class Memoize { 59 | public: 60 | Memoize(std::function func) : 61 | func_(func) 62 | {} 63 | 64 | Rslt operator()() { 65 | if (!result_) { 66 | result_.reset(new Rslt(func_())); 67 | } 68 | return *result_; 69 | } 70 | 71 | private: 72 | std::function func_; 73 | std::unique_ptr result_; 74 | }; 75 | 76 | 77 | auto gc = Memoize(std::getchar); 78 | 79 | bool f() { 80 | std::cout << "Hello!" << std::endl; 81 | return true; 82 | } 83 | 84 | int f2(int x) 85 | { 86 | static int y = 0; 87 | y += x; 88 | return y; 89 | } 90 | 91 | auto mf = Memoize(f); 92 | auto mf2 = Memoize(f2); 93 | 94 | int main(int argc, char** argv) { 95 | std::cout << gc() << "\n" 96 | << gc() << "\n"; 97 | mf(); 98 | mf(); 99 | 100 | std::cout << mf2(42) << " " 101 | << mf2(42) << "\n"; 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-02/challenges/python/solution.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | # 1. Define a higher-order function (or a function object) ``memoize`` in 4 | # your favorite language. This function takes a pure function ``f`` as 5 | # an argument and returns a function that behaves almost exactly like 6 | # ``f``, except that it only calls the original function once for every 7 | # argument, stores the result internally, and subsequently returns this 8 | # stored result every time it’s called with the same argument. 9 | def memoize(f): 10 | results = {} 11 | def m(*x): 12 | try: 13 | return results[x] 14 | except KeyError: 15 | r = f(*x) 16 | results[x] = r 17 | return r 18 | return m 19 | 20 | 21 | # 2. Try to memoize a function from your standard library that you 22 | # normally use to produce random numbers. Does it work? 23 | rand = memoize(lambda x: random.random() * x) 24 | 25 | 26 | def test_rand(): 27 | assert rand(10) == rand(10) 28 | 29 | 30 | # 3. Most random number generators can be initialized with a seed. 31 | # Implement a function that takes a seed, calls the random number 32 | # generator with that seed, and returns the result. Memoize that 33 | # function. Does it work? 34 | def _seed_and_random(a): 35 | random.seed(a) 36 | return random.random() 37 | 38 | seed_and_random = memoize(_seed_and_random) 39 | 40 | def test_seed_and_random(): 41 | assert seed_and_random(42) == seed_and_random(42) 42 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-03/03-categories-great-and-small.md: -------------------------------------------------------------------------------- 1 |    2 |    3 |    4 |    5 |    6 |    7 |    8 |    9 |    10 |    11 |   12 | Categories great and small 13 | ========================== 14 | 15 | - empty category 16 | - make a category from directed graph (free category) 17 | 18 | Orders 19 | ------ 20 | 21 | - preorder (transitive relation) 22 | - partial order (preorder + antisymetric) (no cycles, topo sort) 23 | - total order (comparability: a<=b or b<=a) (can sort) 24 | 25 | hom-set C(a,b) or Hom(a,b) is the set of morphisms from a top b 26 | 27 | - preorder: C(a,b) is singleton or empty 28 | - total: |C(a,b)| + |C(b,a)| = 1 ?? 29 | 30 | Monoid 31 | ------ 32 | 33 | empty element, and associative binary operator 34 | 35 | think 0 and +, * and 1, "" and concat 36 | laws 37 | 38 | x + (y + z) = (x + y) + z 39 | 0 + x = x = x + 0 40 | 41 | Haskell 42 | 43 | class Monoid where 44 | mempty: m 45 | mappend: m -> m -> m 46 | 47 | Currying ok? 48 | mappend x returns a function that "mappends" x to the argument 49 | 50 | mappend x y = (mappend x) y 51 | 52 | Monoid Category 53 | --------------- 54 | 55 | - Morpisms are unary. Mappend is binary 56 | - (+ 5) is a unary function that maps e.g. any number x to x+5 57 | - (+ 5) . (+ 6) = (+ 11) 58 | - (+ 0) is identity 59 | 60 | We get 61 | 62 | - single object categoty 63 | - for each element x in our set, a morphism (mappend x) 64 | - identity (mappend mempty) 65 | - composition 66 | 67 | We can get back to monoid = set, mempty and mappend 68 | 69 | - The set is all mphisms (+ x) 70 | - mempty is identity morphism 71 | - mappend is composition 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/reading-group/part-1/chapter-04/04-kleisli-categories.md: -------------------------------------------------------------------------------- 1 |    2 |    3 |    4 |    5 |    6 |    7 |    8 |    9 |    10 |    11 | 12 | Kleisli Categories 13 | ================== 14 | 15 | Logger 16 | 17 | string logger 18 | bool negate(bool b) { 19 | logger += "Not so! "; 20 | return !b; 21 | } 22 | 23 | We want to simpulate write only side effects without global state 24 | 25 | negate (b, logger) = (!b, logger ++ "Not so! ") 26 | 27 | - Not so good design 28 | - Idea: Only return new log entry, aggregate log between calls 29 | 30 | negate (b) = (!b, "Not so" ") 31 | 32 | Ad hoc Composition 33 | ------------------ 34 | 35 | toUpper s = ... 36 | toWords s = ... 37 | 38 | type Writer a = (a, String) 39 | 40 | toUpper s = (..., "toUpper ") 41 | toWords s = (..., "toWords") 42 | 43 | process s = 44 | let p1 = toUpper s 45 | p2 = toWords (fst p1) 46 | in (fst p2, snd p1 ++ snd p2) 47 | 48 | or 49 | 50 | process s = 51 | let (result1, logger1) = toUpper s 52 | (result2, logger2) = toWords result1 53 | in (result2, logger1 ++ logger2) 54 | 55 | 56 | process "foo bar" = (["FOO", "BAR"], "toUpper toWords ") 57 | 58 | 59 | Better Composition 60 | ------------------ 61 | 62 | Fish = compose any two functions returning a Writer 63 | (>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c) 64 | 65 | (>=>) f1 f2 x = 66 | let (result1, logger1) = f1 x 67 | (result2, logger2) = f2 result1 68 | in (result2, logger1 ++ logger2) 69 | 70 | process s = (toUpper >=> toWords) s 71 | 72 | 73 | 74 | Kleisli Categories 75 | ------------------ 76 | 77 | "Writer a" is called an embellishment of a 78 | 79 | - Category based on a monad (??) 80 | - Objects are types 81 | - Morphism from A to B represents functions from A to the embellished B 82 | 83 | The writer category is a Kleisli Category 84 | 85 | Identity morphism represents a function from A to the emellsihed A 86 | 87 | identity x = (x, "") 88 | 89 | -------------------------------------------------------------------------------- /latest/CategoriesforProgrammers.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/latest/CategoriesforProgrammers.epub -------------------------------------------------------------------------------- /latest/CategoriesforProgrammers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/latest/CategoriesforProgrammers.pdf -------------------------------------------------------------------------------- /latest/create_pdf.sh: -------------------------------------------------------------------------------- 1 | # Convert EPUB to PDF 2 | 3 | pandoc -o CategoriesforProgrammers.pdf --latex-engine=xelatex CategoriesforProgrammers.epub 4 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=CategoriesforProgrammers 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /src/images/2014/10/img_1299.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/10/img_1299.jpg -------------------------------------------------------------------------------- /src/images/2014/10/img_1329.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/10/img_1329.jpg -------------------------------------------------------------------------------- /src/images/2014/10/img_1330.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/10/img_1330.jpg -------------------------------------------------------------------------------- /src/images/2014/12/coproductpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/coproductpattern.jpg -------------------------------------------------------------------------------- /src/images/2014/12/coproductranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/coproductranking.jpg -------------------------------------------------------------------------------- /src/images/2014/12/final.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/final.jpg -------------------------------------------------------------------------------- /src/images/2014/12/initial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/initial.jpg -------------------------------------------------------------------------------- /src/images/2014/12/monoid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/monoid.jpg -------------------------------------------------------------------------------- /src/images/2014/12/monoidhomset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/monoidhomset.jpg -------------------------------------------------------------------------------- /src/images/2014/12/piggyback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/piggyback.jpg -------------------------------------------------------------------------------- /src/images/2014/12/productcandidates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/productcandidates.jpg -------------------------------------------------------------------------------- /src/images/2014/12/productpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/productpattern.jpg -------------------------------------------------------------------------------- /src/images/2014/12/productranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/productranking.jpg -------------------------------------------------------------------------------- /src/images/2014/12/uniqueness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2014/12/uniqueness.jpg -------------------------------------------------------------------------------- /src/images/2015/01/bifunctor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/bifunctor.jpg -------------------------------------------------------------------------------- /src/images/2015/01/bimap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/bimap.jpg -------------------------------------------------------------------------------- /src/images/2015/01/contravariant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/contravariant.jpg -------------------------------------------------------------------------------- /src/images/2015/01/dimap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/dimap.jpg -------------------------------------------------------------------------------- /src/images/2015/01/first.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/first.jpg -------------------------------------------------------------------------------- /src/images/2015/01/functor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/functor.jpg -------------------------------------------------------------------------------- /src/images/2015/01/functorcompos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/functorcompos.jpg -------------------------------------------------------------------------------- /src/images/2015/01/functorid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/functorid.jpg -------------------------------------------------------------------------------- /src/images/2015/01/functormaybe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/functormaybe.jpg -------------------------------------------------------------------------------- /src/images/2015/01/not-a-product.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/not-a-product.jpg -------------------------------------------------------------------------------- /src/images/2015/01/pair.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/pair.jpg -------------------------------------------------------------------------------- /src/images/2015/01/second.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/01/second.jpg -------------------------------------------------------------------------------- /src/images/2015/03/functionpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/functionpattern.jpg -------------------------------------------------------------------------------- /src/images/2015/03/functionranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/functionranking.jpg -------------------------------------------------------------------------------- /src/images/2015/03/functionset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/functionset.jpg -------------------------------------------------------------------------------- /src/images/2015/03/hom-set.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/hom-set.jpg -------------------------------------------------------------------------------- /src/images/2015/03/set-hom-set.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/set-hom-set.jpg -------------------------------------------------------------------------------- /src/images/2015/03/universalfunctionobject.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/03/universalfunctionobject.jpg -------------------------------------------------------------------------------- /src/images/2015/04/10_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/10_horizontal.jpg -------------------------------------------------------------------------------- /src/images/2015/04/1_functors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/1_functors.jpg -------------------------------------------------------------------------------- /src/images/2015/04/2_natcomp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/2_natcomp.jpg -------------------------------------------------------------------------------- /src/images/2015/04/3_naturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/3_naturality.jpg -------------------------------------------------------------------------------- /src/images/2015/04/4_transport.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/4_transport.jpg -------------------------------------------------------------------------------- /src/images/2015/04/5_vertical.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/5_vertical.jpg -------------------------------------------------------------------------------- /src/images/2015/04/6_verticalnaturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/6_verticalnaturality.jpg -------------------------------------------------------------------------------- /src/images/2015/04/6a_vertical.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/6a_vertical.jpg -------------------------------------------------------------------------------- /src/images/2015/04/7_cathomset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/7_cathomset.jpg -------------------------------------------------------------------------------- /src/images/2015/04/8_cat-2-cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/8_cat-2-cat.jpg -------------------------------------------------------------------------------- /src/images/2015/04/9_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/9_horizontal.jpg -------------------------------------------------------------------------------- /src/images/2015/04/asteroids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/asteroids.png -------------------------------------------------------------------------------- /src/images/2015/04/classes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/classes.jpg -------------------------------------------------------------------------------- /src/images/2015/04/colimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/colimit.jpg -------------------------------------------------------------------------------- /src/images/2015/04/cone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/cone.jpg -------------------------------------------------------------------------------- /src/images/2015/04/conecommutativity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/conecommutativity.jpg -------------------------------------------------------------------------------- /src/images/2015/04/conenaturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/conenaturality.jpg -------------------------------------------------------------------------------- /src/images/2015/04/continuity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/continuity.jpg -------------------------------------------------------------------------------- /src/images/2015/04/equalizercone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/equalizercone.jpg -------------------------------------------------------------------------------- /src/images/2015/04/equilizerlimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/equilizerlimit.jpg -------------------------------------------------------------------------------- /src/images/2015/04/feynman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/feynman.jpg -------------------------------------------------------------------------------- /src/images/2015/04/homsetmapping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/homsetmapping.jpg -------------------------------------------------------------------------------- /src/images/2015/04/mortar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/mortar.jpg -------------------------------------------------------------------------------- /src/images/2015/04/natmapping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/natmapping.jpg -------------------------------------------------------------------------------- /src/images/2015/04/naturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/naturality.jpg -------------------------------------------------------------------------------- /src/images/2015/04/productcone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/productcone.jpg -------------------------------------------------------------------------------- /src/images/2015/04/pullbackcone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/pullbackcone.jpg -------------------------------------------------------------------------------- /src/images/2015/04/pullbacklimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/pullbacklimit.jpg -------------------------------------------------------------------------------- /src/images/2015/04/sideways.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/sideways.jpg -------------------------------------------------------------------------------- /src/images/2015/04/snell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/snell.jpg -------------------------------------------------------------------------------- /src/images/2015/04/two.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/two.jpg -------------------------------------------------------------------------------- /src/images/2015/04/twodelta.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/04/twodelta.jpg -------------------------------------------------------------------------------- /src/images/2015/07/bunnies.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/bunnies.jpg -------------------------------------------------------------------------------- /src/images/2015/07/hom-functor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/hom-functor.jpg -------------------------------------------------------------------------------- /src/images/2015/07/hom-set.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/hom-set.jpg -------------------------------------------------------------------------------- /src/images/2015/07/monoid-pattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/monoid-pattern.jpg -------------------------------------------------------------------------------- /src/images/2015/07/monoid-ranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/monoid-ranking.jpg -------------------------------------------------------------------------------- /src/images/2015/07/yoneda-embedding-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/yoneda-embedding-2.jpg -------------------------------------------------------------------------------- /src/images/2015/07/yoneda-embedding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/07/yoneda-embedding.jpg -------------------------------------------------------------------------------- /src/images/2015/08/yoneda1-e1440290035365.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/08/yoneda1-e1440290035365.png -------------------------------------------------------------------------------- /src/images/2015/08/yoneda1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/08/yoneda1.png -------------------------------------------------------------------------------- /src/images/2015/08/yoneda2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/08/yoneda2.png -------------------------------------------------------------------------------- /src/images/2015/09/yoneda3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/09/yoneda3.png -------------------------------------------------------------------------------- /src/images/2015/09/yoneda4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/09/yoneda4.png -------------------------------------------------------------------------------- /src/images/2015/09/yoneda5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/09/yoneda5.png -------------------------------------------------------------------------------- /src/images/2015/11/sheets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2015/11/sheets.png -------------------------------------------------------------------------------- /src/images/2016/04/adj-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-1.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-counit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-counit.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-expo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-expo.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-homsets.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-homsets.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-product.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-product.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-productcat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-productcat.jpg -------------------------------------------------------------------------------- /src/images/2016/04/adj-unit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/04/adj-unit.jpg -------------------------------------------------------------------------------- /src/images/2016/05/forgetful.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/05/forgetful.jpg -------------------------------------------------------------------------------- /src/images/2016/05/forgettingmorphisms.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/05/forgettingmorphisms.jpg -------------------------------------------------------------------------------- /src/images/2016/05/freeimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/05/freeimage.jpg -------------------------------------------------------------------------------- /src/images/2016/05/freemonadjunction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/05/freemonadjunction.jpg -------------------------------------------------------------------------------- /src/images/2016/12/assoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/assoc.png -------------------------------------------------------------------------------- /src/images/2016/12/assoc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/assoc1.png -------------------------------------------------------------------------------- /src/images/2016/12/assoc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/assoc2.png -------------------------------------------------------------------------------- /src/images/2016/12/assocmon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/assocmon.png -------------------------------------------------------------------------------- /src/images/2016/12/assoctensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/assoctensor.jpg -------------------------------------------------------------------------------- /src/images/2016/12/exptree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/exptree.png -------------------------------------------------------------------------------- /src/images/2016/12/horizcomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/horizcomp.png -------------------------------------------------------------------------------- /src/images/2016/12/monoid-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/monoid-1.jpg -------------------------------------------------------------------------------- /src/images/2016/12/unitlawcomp-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/unitlawcomp-1.png -------------------------------------------------------------------------------- /src/images/2016/12/unitlawcomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/unitlawcomp.png -------------------------------------------------------------------------------- /src/images/2016/12/unitmon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2016/12/unitmon.jpg -------------------------------------------------------------------------------- /src/images/2017/02/alg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg.png -------------------------------------------------------------------------------- /src/images/2017/02/alg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg2.png -------------------------------------------------------------------------------- /src/images/2017/02/alg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg3.png -------------------------------------------------------------------------------- /src/images/2017/02/alg3a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg3a.png -------------------------------------------------------------------------------- /src/images/2017/02/alg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg4.png -------------------------------------------------------------------------------- /src/images/2017/02/alg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg5.png -------------------------------------------------------------------------------- /src/images/2017/02/alg6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg6.png -------------------------------------------------------------------------------- /src/images/2017/02/alg7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/alg7.png -------------------------------------------------------------------------------- /src/images/2017/02/triangles-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/triangles-2.png -------------------------------------------------------------------------------- /src/images/2017/02/triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/02/triangles.png -------------------------------------------------------------------------------- /src/images/2017/03/end-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end-1.jpg -------------------------------------------------------------------------------- /src/images/2017/03/end-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end-2.jpg -------------------------------------------------------------------------------- /src/images/2017/03/end-21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end-21.jpg -------------------------------------------------------------------------------- /src/images/2017/03/end-31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end-31.jpg -------------------------------------------------------------------------------- /src/images/2017/03/end.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end.jpg -------------------------------------------------------------------------------- /src/images/2017/03/end1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/end1.jpg -------------------------------------------------------------------------------- /src/images/2017/03/pigalg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/pigalg.png -------------------------------------------------------------------------------- /src/images/2017/03/talg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/talg1.png -------------------------------------------------------------------------------- /src/images/2017/03/talg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/talg2.png -------------------------------------------------------------------------------- /src/images/2017/03/talg31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/talg31.png -------------------------------------------------------------------------------- /src/images/2017/03/talg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/talg4.png -------------------------------------------------------------------------------- /src/images/2017/03/talg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/03/talg5.png -------------------------------------------------------------------------------- /src/images/2017/04/kan10a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan10a.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan10b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan10b.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan112.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan112.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan12.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan13.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan14.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan15.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan2.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan3-e1492120491591.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan3-e1492120491591.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan31-e1492120512209.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan31-e1492120512209.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan5.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan6.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan7.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan81.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan81.jpg -------------------------------------------------------------------------------- /src/images/2017/04/kan92.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/04/kan92.jpg -------------------------------------------------------------------------------- /src/images/2017/05/assoc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/assoc.jpg -------------------------------------------------------------------------------- /src/images/2017/05/compcoherence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/compcoherence.jpg -------------------------------------------------------------------------------- /src/images/2017/05/composition.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/composition.jpg -------------------------------------------------------------------------------- /src/images/2017/05/functorcomp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/functorcomp.jpg -------------------------------------------------------------------------------- /src/images/2017/05/functorid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/functorid.jpg -------------------------------------------------------------------------------- /src/images/2017/05/id.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/id.jpg -------------------------------------------------------------------------------- /src/images/2017/05/idcoherence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/idcoherence.jpg -------------------------------------------------------------------------------- /src/images/2017/05/leftid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/leftid.jpg -------------------------------------------------------------------------------- /src/images/2017/05/rightid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/05/rightid.jpg -------------------------------------------------------------------------------- /src/images/2017/07/monomorphism.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/07/monomorphism.jpg -------------------------------------------------------------------------------- /src/images/2017/07/notmono.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/07/notmono.jpg -------------------------------------------------------------------------------- /src/images/2017/07/pullback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/07/pullback.jpg -------------------------------------------------------------------------------- /src/images/2017/07/subsetinjection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/07/subsetinjection.jpg -------------------------------------------------------------------------------- /src/images/2017/07/true.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/07/true.jpg -------------------------------------------------------------------------------- /src/images/2017/08/equalize1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/08/equalize1.png -------------------------------------------------------------------------------- /src/images/2017/08/equalize2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/08/equalize2.png -------------------------------------------------------------------------------- /src/images/2017/08/lawvere1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/08/lawvere1.png -------------------------------------------------------------------------------- /src/images/2017/08/liftl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/08/liftl.png -------------------------------------------------------------------------------- /src/images/2017/08/liftpower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/08/liftpower.png -------------------------------------------------------------------------------- /src/images/2017/09/bicat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/bicat.png -------------------------------------------------------------------------------- /src/images/2017/09/bimonad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/bimonad.png -------------------------------------------------------------------------------- /src/images/2017/09/compspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/compspan.png -------------------------------------------------------------------------------- /src/images/2017/09/monad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/monad.png -------------------------------------------------------------------------------- /src/images/2017/09/morphspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/morphspan.png -------------------------------------------------------------------------------- /src/images/2017/09/pullspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/pullspan.png -------------------------------------------------------------------------------- /src/images/2017/09/span.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/span.png -------------------------------------------------------------------------------- /src/images/2017/09/spanmonad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/spanmonad.png -------------------------------------------------------------------------------- /src/images/2017/09/spanmul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/spanmul.png -------------------------------------------------------------------------------- /src/images/2017/09/spanunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/spanunit.png -------------------------------------------------------------------------------- /src/images/2017/09/twocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abingham/categories-for-programmers/fede62409dbddc75bb0e5ba62bc6e73c49901dd6/src/images/2017/09/twocat.png -------------------------------------------------------------------------------- /src/index.rst: -------------------------------------------------------------------------------- 1 | .. Categories for Programmers documentation master file, created by 2 | sphinx-quickstart on Sun Sep 3 19:50:50 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Categories for Programmers 7 | ========================== 8 | 9 | :Author: 10 | Bartosz Milewski 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | 15 | preface 16 | 17 | .. toctree:: 18 | :maxdepth: 1 19 | :glob: 20 | :numbered: 21 | 22 | part1/* 23 | part2/* 24 | part3/* 25 | -------------------------------------------------------------------------------- /src/part1/01-category-the-essence-of-computing.rst: -------------------------------------------------------------------------------- 1 | ====================================== 2 | Category: The Essence of Composition 3 | ====================================== 4 | 5 | A category is an embarrassingly simple concept. A category consists of 6 | objects and arrows that go between them. That’s why categories are so 7 | easy to represent pictorially. An object can be drawn as a circle or a 8 | point, and an arrow… is an arrow. (Just for variety, I will occasionally 9 | draw objects as piggies and arrows as fireworks.) But the essence of a 10 | category is composition. Or, if you prefer, the essence of composition 11 | is a category. Arrows compose, so if you have an arrow from object A to 12 | object B, and another arrow from object B to object C, then there must 13 | be an arrow — their composition — that goes from A to C. 14 | 15 | |IMG_1330| 16 | In a category, if there is an arrow going from A to B and an arrow going 17 | from B to C then there must also be a direct arrow from A to C that is 18 | their composition. This diagram is not a full category because it’s 19 | missing identity morphisms (see later). 20 | 21 | Arrows as Functions 22 | =================== 23 | 24 | Is this already too much abstract nonsense? Do not despair. Let’s talk 25 | concretes. Think of arrows, which are also called *morphisms*, as 26 | functions. You have a function f that takes an argument of type A and 27 | returns a B. You have another function g that takes a B and returns a C. 28 | You can compose them by passing the result of f to g. You have just 29 | defined a new function that takes an A and returns a C. 30 | 31 | In math, such composition is denoted by a small circle between 32 | functions: g∘f. Notice the right to left order of composition. For some 33 | people this is confusing. You may be familiar with the pipe notation in 34 | Unix, as in: 35 | 36 | :: 37 | 38 | lsof | grep Chrome 39 | 40 | or the chevron ``>>`` in F#, which both go from left to right. But in 41 | mathematics and in Haskell functions compose right to left. It helps if 42 | you read g∘f as “g *after* f.” 43 | 44 | Let’s make this even more explicit by writing some C code. We have one 45 | function ``f`` that takes an argument of type ``A`` and returns a value 46 | of type ``B``: 47 | 48 | .. code-block:: c 49 | 50 | B f(A a); 51 | 52 | and another: 53 | 54 | .. code-block:: c 55 | 56 | C g(B b); 57 | 58 | Their composition is: 59 | 60 | .. code-block:: c 61 | 62 | C g_after_f(A a) 63 | { 64 | return g(f(a)); 65 | } 66 | 67 | Here, again, you see right-to-left composition: ``g(f(a))``; this time 68 | in C. 69 | 70 | I wish I could tell you that there is a template in the C++ Standard 71 | Library that takes two functions and returns their composition, but 72 | there isn’t one. So let’s try some Haskell for a change. Here’s the 73 | declaration of a function from A to B: 74 | 75 | .. code-block:: haskell 76 | 77 | f :: A -> B 78 | 79 | Similarly: 80 | 81 | .. code-block:: haskell 82 | 83 | g :: B -> C 84 | 85 | Their composition is: 86 | 87 | .. code-block:: haskell 88 | 89 | g . f 90 | 91 | Once you see how simple things are in Haskell, the inability to express 92 | straightforward functional concepts in C++ is a little embarrassing. In 93 | fact, Haskell will let you use Unicode characters so you can write 94 | composition as: 95 | 96 | :: 97 | 98 | g ∘ f 99 | 100 | You can even use Unicode double colons and arrows: 101 | 102 | :: 103 | 104 | f ∷ A → B 105 | 106 | So here’s the first Haskell lesson: Double colon means “has the type 107 | of…” A function type is created by inserting an arrow between two types. 108 | You compose two functions by inserting a period between them (or a 109 | Unicode circle). 110 | 111 | Properties of Composition 112 | ========================= 113 | 114 | There are two extremely important properties that the composition in any 115 | category must satisfy. 116 | 117 | Property 1: Composition is associative 118 | -------------------------------------- 119 | 120 | If you have three morphisms, f, g, and h, that can be composed (that is, their 121 | objects match end-to-end), you don’t need parentheses to compose them. In math 122 | notation this is expressed as: 123 | 124 | :: 125 | 126 | h∘(g∘f) = (h∘g)∘f = h∘g∘f 127 | 128 | In (pseudo) Haskell: 129 | 130 | .. code-block:: haskell 131 | 132 | f :: A -> B 133 | g :: B -> C 134 | h :: C -> D 135 | h . (g . f) == (h . g) . f == h . g . f 136 | 137 | (I said “pseudo,” because equality is not defined for functions.) 138 | 139 | Associativity is pretty obvious when dealing with functions, but it may 140 | be not as obvious in other categories. 141 | 142 | Property 2: For every object A there is an arrow which is a unit of composition 143 | ------------------------------------------------------------------------------- 144 | 145 | This arrow loops from the object to itself. Being a unit of composition 146 | means that, when composed with any arrow that either starts at A or ends 147 | at A, respectively, it gives back the same arrow. The unit arrow for 148 | object A is called id\ :sub:`A` (identity on A). In math notation, if f 149 | goes from A to B then 150 | 151 | :: 152 | 153 | f∘idA = f 154 | 155 | and 156 | 157 | :: 158 | 159 | idB∘f = f 160 | 161 | When dealing with functions, the identity arrow is implemented as the 162 | identity function that just returns back its argument. The 163 | implementation is the same for every type, which means this function is 164 | universally polymorphic. In C++ we could define it as a template: 165 | 166 | .. code-block:: c++ 167 | 168 | template T id(T x) { return x; } 169 | 170 | Of course, in C++ nothing is that simple, because you have to take into 171 | account not only what you’re passing but also how (that is, by value, by 172 | reference, by const reference, by move, and so on). c++ 173 | 174 | In Haskell, the identity function is part of the standard library 175 | (called Prelude). Here’s its declaration and definition: 176 | 177 | .. code-block:: haskell 178 | 179 | id :: a -> a 180 | id x = x 181 | 182 | As you can see, polymorphic functions in Haskell are a piece of cake. In 183 | the declaration, you just replace the type with a type variable. Here’s 184 | the trick: names of concrete types always start with a capital letter, 185 | names of type variables start with a lowercase letter. So here ``a`` 186 | stands for all types. 187 | 188 | Haskell function definitions consist of the name of the function 189 | followed by formal parameters — here just one, ``x``. The body of the 190 | function follows the equal sign. This terseness is often shocking to 191 | newcomers but you will quickly see that it makes perfect sense. Function 192 | definition and function call are the bread and butter of functional 193 | programming so their syntax is reduced to the bare minimum. Not only are 194 | there no parentheses around the argument list but there are no commas 195 | between arguments (you’ll see that later, when we define functions of 196 | multiple arguments). 197 | 198 | The body of a function is always an expression — there are no statements 199 | in functions. The result of a function is this expression — here, just 200 | ``x``. 201 | 202 | This concludes our second Haskell lesson. 203 | 204 | The identity conditions can be written (again, in pseudo-Haskell) as: 205 | 206 | .. code-block:: haskell 207 | 208 | f . id == f 209 | id . f == f 210 | 211 | You might be asking yourself the question: Why would anyone bother with 212 | the identity function — a function that does nothing? Then again, why do 213 | we bother with the number zero? Zero is a symbol for nothing. Ancient 214 | Romans had a number system without a zero and they were able to build 215 | excellent roads and aqueducts, some of which survive to this day. 216 | 217 | Neutral values like zero or ``id`` are extremely useful when working 218 | with symbolic variables. That’s why Romans were not very good at 219 | algebra, whereas the Arabs and the Persians, who were familiar with the 220 | concept of zero, were. So the identity function becomes very handy as an 221 | argument to, or a return from, a higher-order function. Higher order 222 | functions are what make symbolic manipulation of functions possible. 223 | They are the algebra of functions. 224 | 225 | To summarize: A category consists of objects and arrows (morphisms). 226 | Arrows can be composed, and the composition is associative. Every object 227 | has an identity arrow that serves as a unit under composition. 228 | 229 | Composition is the Essence of Programming 230 | ========================================= 231 | 232 | Functional programmers have a peculiar way of approaching problems. They 233 | start by asking very Zen-like questions. For instance, when designing an 234 | interactive program, they would ask: What is interaction? When 235 | implementing Conway’s Game of Life, they would probably ponder about the 236 | meaning of life. In this spirit, I’m going to ask: What is programming? 237 | At the most basic level, programming is about telling the computer what 238 | to do. “Take the contents of memory address x and add it to the contents 239 | of the register EAX.” But even when we program in assembly, the 240 | instructions we give the computer are an expression of something more 241 | meaningful. We are solving a non-trivial problem (if it were trivial, we 242 | wouldn’t need the help of the computer). And how do we solve problems? 243 | We decompose bigger problems into smaller problems. If the smaller 244 | problems are still too big, we decompose them further, and so on. 245 | Finally, we write code that solves all the small problems. And then 246 | comes the essence of programming: we compose those pieces of code to 247 | create solutions to larger problems. Decomposition wouldn’t make sense 248 | if we weren’t able to put the pieces back together. 249 | 250 | This process of hierarchical decomposition and recomposition is not 251 | imposed on us by computers. It reflects the limitations of the human 252 | mind. Our brains can only deal with a small number of concepts at a 253 | time. One of the most cited papers in psychology, `The Magical Number 254 | Seven, Plus or Minus 255 | Two `__, 256 | postulated that we can only keep 7 ± 2 “chunks” of information in our 257 | minds. The details of our understanding of the human short-term memory 258 | might be changing, but we know for sure that it’s limited. The bottom 259 | line is that we are unable to deal with the soup of objects or the 260 | spaghetti of code. We need structure not because well-structured 261 | programs are pleasant to look at, but because otherwise our brains can’t 262 | process them efficiently. We often describe some piece of code as 263 | elegant or beautiful, but what we really mean is that it’s easy to 264 | process by our limited human minds. Elegant code creates chunks that are 265 | just the right size and come in just the right number for our mental 266 | digestive system to assimilate them. 267 | 268 | So what are the right chunks for the composition of programs? Their 269 | surface area has to increase slower than their volume. (I like this 270 | analogy because of the intuition that the surface area of a geometric 271 | object grows with the square of its size — slower than the volume, which 272 | grows with the cube of its size.) The surface area is the information we 273 | need in order to compose chunks. The volume is the information we need 274 | in order to implement them. The idea is that, once a chunk is 275 | implemented, we can forget about the details of its implementation and 276 | concentrate on how it interacts with other chunks. In object-oriented 277 | programming, the surface is the class declaration of the object, or its 278 | abstract interface. In functional programming, it’s the declaration of a 279 | function. (I’m simplifying things a bit, but that’s the gist of it.) 280 | 281 | Category theory is extreme in the sense that it actively discourages us 282 | from looking inside the objects. An object in category theory is an 283 | abstract nebulous entity. All you can ever know about it is how it 284 | relates to other object — how it connects with them using arrows. This 285 | is how internet search engines rank web sites by analyzing incoming and 286 | outgoing links (except when they cheat). In object-oriented programming, 287 | an idealized object is only visible through its abstract interface (pure 288 | surface, no volume), with methods playing the role of arrows. The moment 289 | you have to dig into the implementation of the object in order to 290 | understand how to compose it with other objects, you’ve lost the 291 | advantages of your programming paradigm. 292 | 293 | Challenges 294 | ========== 295 | 296 | #. Implement, as best as you can, the identity function in your favorite 297 | language (or the second favorite, if your favorite language happens 298 | to be Haskell). 299 | #. Implement the composition function in your favorite language. It 300 | takes two functions as arguments and returns a function that is their 301 | composition. 302 | #. Write a program that tries to test that your composition function 303 | respects identity. 304 | #. Is the world-wide web a category in any sense? Are links morphisms? 305 | #. Is Facebook a category, with people as objects and friendships as 306 | morphisms? 307 | #. When is a directed graph a category? 308 | 309 | .. |IMG_1330| image:: ../images/2014/10/img_1330.jpg 310 | :class: wp-image-3483 size-large 311 | :width: 510px 312 | :height: 218px 313 | :target: ../images/2014/10/img_1330.jpg 314 | -------------------------------------------------------------------------------- /src/part2/11-declarative-programming.rst: -------------------------------------------------------------------------------- 1 | =========================================== 2 | Category Theory and Declarative Programming 3 | =========================================== 4 | 5 | In the first part of the book I argued that both category theory and 6 | programming are about composability. In programming, you keep 7 | decomposing a problem until you reach the level of detail that you can 8 | deal with, solve each subproblem in turn, and re-compose the solutions 9 | bottom-up. There are, roughly speaking, two ways of doing it: by telling 10 | the computer what to do, or by telling it how to do it. One is called 11 | declarative and the other imperative. 12 | 13 | You can see this even at the most basic level. Composition itself may be 14 | defined declaratively; as in, ``h`` is a composite of ``g`` after ``f``: 15 | 16 | .. code-block:: haskell 17 | 18 | h = g . f 19 | 20 | or imperatively; as in, call ``f`` first, remember the result of that 21 | call, then call ``g`` with the result: 22 | 23 | .. code-block:: haskell 24 | 25 | h x = let y = f x 26 | in g y 27 | 28 | The imperative version of a program is usually described as a sequence 29 | of actions ordered in time. In particular, the call to ``g`` cannot 30 | happen before the execution of ``f`` completes. At least, that’s the 31 | conceptual picture — in a lazy language, with *call-by-need* argument 32 | passing, the actual execution may proceed differently. 33 | 34 | In fact, depending on the cleverness of the compiler, there may be 35 | little or no difference between how declarative and imperative code is 36 | executed. But the two methodologies differ, sometimes drastically, in 37 | the way we approach problem solving and in the maintainability and 38 | testability of the resulting code. 39 | 40 | The main question is: when faced with a problem, do we always have the 41 | choice between a declarative and imperative approaches to solving it? 42 | And, if there is a declarative solution, can it always be translated 43 | into computer code? The answer to this question is far from obvious and, 44 | if we could find it, we would probably revolutionize our understanding 45 | of the universe. 46 | 47 | Let me elaborate. There is a similar duality in physics, which either 48 | points at some deep underlying principle, or tells us something about 49 | how our minds work. Richard Feynman mentions this duality as an 50 | inspiration in his own work on quantum electrodynamics. 51 | 52 | There are two forms of expressing most laws of physics. One uses local, 53 | or infinitesimal, considerations. We look at the state of a system 54 | around a small neighborhood, and predict how it will evolve within the 55 | next instant of time. This is usually expressed using differential 56 | equations that have to be integrated, or summed up, over a period of 57 | time. 58 | 59 | Notice how this approach resembles imperative thinking: we reach the 60 | final solution by following a sequence of small steps, each depending on 61 | the result of the previous one. In fact, computer simulations of 62 | physical systems are routinely implemented by turning differential 63 | equations into difference equations and iterating them. This is how 64 | spaceships are animated in the asteroids game. At each time step, the 65 | position of a spaceship is changed by adding a small increment, which is 66 | calculated by multiplying its velocity by the time delta. The velocity, 67 | in turn, is changed by a small increment proportional to acceleration, 68 | which is given by force divided by mass. 69 | 70 | |Asteroids| 71 | 72 | These are the direct encodings of the differential equations 73 | corresponding to Newton’s laws of motion: 74 | 75 | :: 76 | 77 | F = m dv/dt 78 | v = dx/dt 79 | 80 | Similar methods may be applied to more complex problems, like the 81 | propagation of electromagnetic fields using Maxwell’s equations, or even 82 | the behavior of quarks and gluons inside a proton using lattice QCD 83 | (quantum chromodynamics). 84 | 85 | This local thinking combined with discretization of space and time that 86 | is encouraged by the use of digital computers found its extreme 87 | expression in the heroic attempt by Stephen Wolfram to reduce the 88 | complexity of the whole universe to a system of cellular automata. 89 | 90 | The other approach is global. We look at the initial and the final state 91 | of the system, and calculate a trajectory that connects them by 92 | minimizing a certain functional. The simplest example is the Fermat’s 93 | principle of least time. It states that light rays propagate along paths 94 | that minimize their flight time. In particular, in the absence of 95 | reflecting or refracting objects, a light ray from point A to point B 96 | will take the shortest path, which is a straight line. But light 97 | propagates slower in dense (transparent) materials, like water or glass. 98 | So if you pick the starting point in the air, and the ending point under 99 | water, it’s more advantageous for light to travel longer in the air and 100 | then take a shortcut through water. The path of minimum time makes the 101 | ray refract at the boundary of air and water, resulting in Snell’s law 102 | of refraction: 103 | 104 | :: 105 | 106 | sin θ1 / sin θ2 = v1 / v2 107 | 108 | where ``v1`` is the speed of light in the air and ``v2`` is the speed of 109 | light in the water. 110 | 111 | |Snell| 112 | 113 | All of classical mechanics can be derived from the principle of least 114 | action. The action can be calculated for any trajectory by integrating 115 | the Lagrangian, which is the difference between kinetic and potential 116 | energy (notice: it’s the difference, not the sum — the sum would be the 117 | total energy). When you fire a mortar to hit a given target, the 118 | projectile will first go up, where the potential energy due to gravity 119 | is higher, and spend some time there racking up negative contribution to 120 | the action. It will also slow down at the top of the parabola, to 121 | minimize kinetic energy. Then it will speed up to go quickly through the 122 | area of low potential energy. 123 | 124 | |Mortar| 125 | 126 | Feynman’s greatest contribution was to realize that the principle of 127 | least action can be generalized to quantum mechanics. There, again, the 128 | problem is formulated in terms of initial state and final state. The 129 | Feynman path integral between those states is used to calculate the 130 | probability of transition. 131 | 132 | |Feynman| 133 | 134 | The point is that there is a curious unexplained duality in the way we 135 | can describe the laws of physics. We can use the local picture, in which 136 | things happen sequentially and in small increments. Or we can use the 137 | global picture, where we declare the initial and final conditions, and 138 | everything in between just follows. 139 | 140 | The global approach can be also used in programming, for instance when 141 | implementing ray tracing. We declare the position of the eye and the 142 | positions of light sources, and figure out the paths that the light rays 143 | may take to connect them. We don’t explicitly minimize the time of 144 | flight for each ray, but we do use Snell’s law and the geometry of 145 | reflection to the same effect. 146 | 147 | The biggest difference between the local and the global approach is in 148 | their treatment of space and, more importantly, time. The local approach 149 | embraces the immediate gratification of here and now, whereas the global 150 | approach takes a long-term static view, as if the future had been 151 | preordained, and we were only analyzing the properties of some eternal 152 | universe. 153 | 154 | Nowhere is it better illustrated than in the Functional Reactive 155 | Programming approach to user interaction. Instead of writing separate 156 | handlers for every possible user action, all having access to some 157 | shared mutable state, FRP treats external events as an infinite list, 158 | and applies a series of transformations to it. Conceptually, the list of 159 | all our future actions is there, available as the input data to our 160 | program. From a program’s perspective there’s no difference between the 161 | list of digits of π, a list of pseudo-random numbers, or a list of mouse 162 | positions coming through computer hardware. In each case, if you want to 163 | get the nth item, you have to first go through the first n-1 items. When 164 | applied to temporal events, we call this property *causality*. 165 | 166 | So what does it have to do with category theory? I will argue that 167 | category theory encourages a global approach and therefore supports 168 | declarative programming. First of all, unlike calculus, it has no 169 | built-in notion of distance, or neighborhood, or time. All we have is 170 | abstract objects and abstract connections between them. If you can get 171 | from A to B through a series of steps, you can also get there in one 172 | leap. Moreover, the major tool of category theory is the universal 173 | construction, which is the epitome of a global approach. We’ve seen it 174 | in action, for instance, in the definition of the categorical product. 175 | It was done by specifying its properties — a very declarative approach. 176 | It’s an object equipped with two projections, and it’s the best such 177 | object — it optimizes a certain property: the property of factorizing 178 | the projections of other such objects. 179 | 180 | | |ProductRanking| 181 | | Compare this with Fermat’s principle of minimum time, or the principle 182 | of least action. 183 | 184 | Conversely, contrast this with the traditional definition of a cartesian 185 | product, which is much more imperative. You describe how to create an 186 | element of the product by picking one element from one set and another 187 | element from another set. It’s a recipe for creating a pair. And there’s 188 | another for disassembling a pair. 189 | 190 | In almost every programming language, including functional languages 191 | like Haskell, product types, coproduct types, and function types are 192 | built in, rather than being defined by universal constructions; although 193 | there have been attempts at creating categorical programming languages 194 | (see, e.g., `Tatsuya Hagino’s 195 | thesis `__). 196 | 197 | Whether used directly or not, categorical definitions justify 198 | pre-existing programming constructs, and give rise to new ones. Most 199 | importantly, category theory provides a meta-language for reasoning 200 | about computer programs at a declarative level. It also encourages 201 | reasoning about problem specification before it is cast into code. 202 | 203 | Acknowledgments 204 | =============== 205 | 206 | I’d like to thank Gershom Bazerman for checking my math and logic, and André van 207 | Meulebrouck, who has been volunteering his editing help. 208 | 209 | .. |Asteroids| image:: ../images/2015/04/asteroids.png 210 | :class: alignnone size-medium wp-image-4432 211 | :width: 300px 212 | :height: 225px 213 | :target: ../images/2015/04/asteroids.png 214 | .. |Snell| image:: ../images/2015/04/snell.jpg 215 | :class: alignnone size-medium wp-image-4437 216 | :width: 224px 217 | :height: 300px 218 | :target: ../images/2015/04/snell.jpg 219 | .. |Mortar| image:: ../images/2015/04/mortar.jpg 220 | :class: alignnone size-medium wp-image-4438 221 | :width: 300px 222 | :height: 158px 223 | :target: ../images/2015/04/mortar.jpg 224 | .. |Feynman| image:: ../images/2015/04/feynman.jpg 225 | :class: alignnone size-medium wp-image-4439 226 | :width: 300px 227 | :height: 225px 228 | :target: ../images/2015/04/feynman.jpg 229 | .. |ProductRanking| image:: ../images/2014/12/productranking.jpg 230 | :class: alignnone size-medium wp-image-3772 231 | :width: 300px 232 | :height: 244px 233 | :target: ../images/2014/12/productranking.jpg 234 | -------------------------------------------------------------------------------- /src/part2/13-free-monoids.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Free Monoids 3 | ============ 4 | 5 | Monoids are an important concept in both category theory and in 6 | programming. Categories correspond to strongly typed languages, monoids 7 | to untyped languages. That’s because in a monoid you can compose any two 8 | arrows, just as in an untyped language you can compose any two functions 9 | (of course, you may end up with a runtime error when you execute your 10 | program). 11 | 12 | We’ve seen that a monoid may be described as a category with a single 13 | object, where all logic is encoded in the rules of morphism composition. 14 | This categorical model is fully equivalent to the more traditional 15 | set-theoretical definition of a monoid, where we “multiply” two elements 16 | of a set to get a third element. This process of “multiplication” can be 17 | further dissected into first forming a pair of elements and then 18 | identifying this pair with an existing element — their “product.” 19 | 20 | What happens when we forgo the second part of multiplication — the 21 | identification of pairs with existing elements? We can, for instance, 22 | start with an arbitrary set, form all possible pairs of elements, and 23 | call them new elements. Then we’ll pair these new elements with all 24 | possible elements, and so on. This is a chain reaction — we’ll keep 25 | adding new elements forever. The result, an infinite set, will be 26 | *almost* a monoid. But a monoid also needs a unit element and the law of 27 | associativity. No problem, we can add a special unit element and 28 | identify some of the pairs — just enough to support the unit and 29 | associativity laws. 30 | 31 | Let’s see how this works in a simple example. Let’s start with a set of 32 | two elements, ``{a, b}``. We’ll call them the generators of the free 33 | monoid. First, we’ll add a special element ``e`` to serve as the unit. 34 | Next we’ll add all the pairs of elements and call them “products”. The 35 | product of ``a`` and ``b`` will be the pair ``(a, b)``. The product of 36 | ``b`` and ``a`` will be the pair ``(b, a)``, the product of ``a`` with 37 | ``a`` will be ``(a, a)``, the product of ``b`` with ``b`` will be 38 | ``(b, b)``. We can also form pairs with ``e``, like ``(a, e)``, 39 | ``(e, b)``, etc., but we’ll identify them with ``a``, ``b``, etc. So in 40 | this round we’ll only add ``(a, a)``, ``(a, b)`` and ``(b, a)`` and 41 | ``(b, b)``, and end up with the set 42 | ``{e, a, b, (a, a), (a, b), (b, a), (b, b)}``. 43 | 44 | |Bunnies| 45 | 46 | In the next round we’ll keep adding elements like: ``(a, (a, b))``, 47 | ``((a, b), a)``, etc. At this point we’ll have to make sure that 48 | associativity holds, so we’ll identify ``(a, (b, a))`` with 49 | ``((a, b), a)``, etc. In other words, we won’t be needing internal 50 | parentheses. 51 | 52 | You can guess what the final result of this process will be: we’ll 53 | create all possible lists of ``a``\ s and ``b``\ s. In fact, if we 54 | represent ``e`` as an empty list, we can see that our “multiplication” 55 | is nothing but list concatenation. 56 | 57 | This kind of construction, in which you keep generating all possible 58 | combinations of elements, and perform the minimum number of 59 | identifications — just enough to uphold the laws — is called a free 60 | construction. What we have just done is to construct a *free monoid* 61 | from the set of generators ``{a, b}``. 62 | 63 | Free Monoid in Haskell 64 | ====================== 65 | 66 | A two-element set in Haskell is equivalent to the type ``Bool``, and the 67 | free monoid generated by this set is equivalent to the type ``[Bool]`` 68 | (list of ``Bool``). (I am deliberately ignoring problems with infinite 69 | lists.) 70 | 71 | A monoid in Haskell is defined by the type class: 72 | 73 | .. code-block:: haskell 74 | 75 | class Monoid m where 76 | mempty :: m 77 | mappend :: m -> m -> m 78 | 79 | This just says that every ``Monoid`` must have a neutral element, which 80 | is called ``mempty``, and a binary function (multiplication) called 81 | ``mappend``. The unit and associativity laws cannot be expressed in 82 | Haskell and must be verified by the programmer every time a monoid is 83 | instantiated. 84 | 85 | The fact that a list of any type forms a monoid is described by this 86 | instance definition: 87 | 88 | .. code-block:: haskell 89 | 90 | instance Monoid [a] where 91 | mempty = [] 92 | mappend = (++) 93 | 94 | It states that an empty list ``[]`` is the unit element, and list 95 | concatenation ``(++)`` is the binary operation. 96 | 97 | As we have seen, a list of type ``a`` corresponds to a free monoid with 98 | the set ``a`` serving as generators. The set of natural numbers with 99 | multiplication is not a free monoid, because we identify lots of 100 | products. Compare for instance: 101 | 102 | .. code-block:: haskell 103 | 104 | 2 * 3 = 6 105 | [2] ++ [3] = [2, 3] // not the same as [6] 106 | 107 | That was easy, but the question is, can we perform this free 108 | construction in category theory, where we are not allowed to look inside 109 | objects? We’ll use our workhorse: the universal construction. 110 | 111 | The second interesting question is, can any monoid be obtained from some 112 | free monoid by identifying more than the minimum number of elements 113 | required by the laws? I’ll show you that this follows directly from the 114 | universal construction. 115 | 116 | Free Monoid Universal Construction 117 | ================================== 118 | 119 | If you recall our previous experiences with universal constructions, you 120 | might notice that it’s not so much about constructing something as about 121 | selecting an object that best fits a given pattern. So if we want to use 122 | the universal construction to “construct” a free monoid, we have to 123 | consider a whole bunch of monoids from which to pick one. We need a 124 | whole category of monoids to chose from. But do monoids form a category? 125 | 126 | Let’s first look at monoids as sets equipped with additional structure 127 | defined by unit and multiplication. We’ll pick as morphisms those 128 | functions that preserve the monoidal structure. Such 129 | structure-preserving functions are called *homomorphisms*. A monoid 130 | homomorphism must map the product of two elements to the product of the 131 | mapping of the two elements: 132 | 133 | .. code-block:: haskell 134 | 135 | h (a * b) = h a * h b 136 | 137 | | and it must map unit to unit. 138 | | For instance, consider a homomorphism from lists of integers to 139 | integers. If we map ``[2]`` to 2 and ``[3]`` to 3, we have to map 140 | ``[2, 3]`` to 6, because concatenation 141 | 142 | .. code-block:: haskell 143 | 144 | [2] ++ [3] = [2, 3] 145 | 146 | becomes multiplication 147 | 148 | .. code-block:: haskell 149 | 150 | 2 * 3 = 6 151 | 152 | Now let’s forget about the internal structure of individual monoids, and 153 | only look at them as objects with corresponding morphisms. You get a 154 | category **Mon** of monoids. 155 | 156 | Okay, maybe before we forget about internal structure, let us notice an 157 | important property. Every object of **Mon** can be trivially mapped to a 158 | set. It’s just the set of its elements. This set is called the 159 | *underlying* set. In fact, not only can we map objects of **Mon** to 160 | sets, but we can also map morphisms of **Mon** (homomorphisms) to 161 | functions. Again, this seems sort of trivial, but it will become useful 162 | soon. This mapping of objects and morphisms from **Mon** to **Set** is 163 | in fact a functor. Since this functor “forgets” the monoidal structure — 164 | once we are inside a plain set, we no longer distinguish the unit 165 | element or care about multiplication — it’s called a *forgetful 166 | functor*. Forgetful functors come up regularly in category theory. 167 | 168 | We now have two different views of **Mon**. We can treat it just like 169 | any other category with objects and morphisms. In that view, we don’t 170 | see the internal structure of monoids. All we can say about a particular 171 | object in **Mon** is that it connects to itself and to other objects 172 | through morphisms. The “multiplication” table of morphisms — the 173 | composition rules — are derived from the other view: monoids-as-sets. By 174 | going to category theory we haven’t lost this view completely — we can 175 | still access it through our forgetful functor. 176 | 177 | To apply the universal construction, we need to define a special 178 | property that would let us search through the category of monoids and 179 | pick the best candidate for a free monoid. But a free monoid is defined 180 | by its generators. Different choices of generators produce different 181 | free monoids (a list of ``Bool`` is not the same as a list of ``Int``). 182 | Our construction must start with a set of generators. So we’re back to 183 | sets! 184 | 185 | That’s where the forgetful functor comes into play. We can use it to 186 | X-ray our monoids. We can identify the generators in the X-ray images of 187 | those blobs. Here’s how it works: 188 | 189 | We start with a set of generators, ``x``. That’s a set in **Set**. 190 | 191 | The pattern we are going to match consists of a monoid ``m`` — an object 192 | of **Mon** — and a function ``p`` in **Set**: 193 | 194 | .. code-block:: haskell 195 | 196 | p :: x -> U m 197 | 198 | where ``U`` is our forgetful functor from **Mon** to **Set**. This is a 199 | weird heterogeneous pattern — half in **Mon** and half in **Set**. 200 | 201 | The idea is that the function ``p`` will identify the set of generators 202 | inside the X-ray image of ``m``. It doesn’t matter that functions may be 203 | lousy at identifying points inside sets (they may collapse them). It 204 | will all be sorted out by the universal construction, which will pick 205 | the best representative of this pattern. 206 | 207 | |Monoid Pattern| 208 | 209 | We also have to define the ranking among candidates. Suppose we have 210 | another candidate: a monoid ``n`` and a function that identifies the 211 | generators in its X-ray image: 212 | 213 | .. code-block:: haskell 214 | 215 | q :: x -> U n 216 | 217 | We’ll say that ``m`` is better than ``n`` if there is a morphism of 218 | monoids (that’s a structure-preserving homomorphism): 219 | 220 | .. code-block:: haskell 221 | 222 | h :: m -> n 223 | 224 | whose image under ``U`` (remember, ``U`` is a functor, so it maps 225 | morphisms to functions) factorizes through ``p``: 226 | 227 | .. code-block:: haskell 228 | 229 | q = U h . p 230 | 231 | If you think of ``p`` as selecting the generators in ``m``; and ``q`` as 232 | selecting “the same” generators in ``n``; then you can think of ``h`` as 233 | mapping these generators between the two monoids. Remember that ``h``, 234 | by definition, preserves the monoidal structure. It means that a product 235 | of two generators in one monoid will be mapped to a product of the 236 | corresponding two generators in the second monoid, and so on. 237 | 238 | |Monoid Ranking| 239 | 240 | This ranking may be used to find the best candidate — the free monoid. 241 | Here’s the definition: 242 | 243 | We’ll say that ``m`` (together with the function ``p``) is the **free 244 | monoid** with the generators ``x`` if and only if there is a *unique* 245 | morphism ``h`` from ``m`` to any other monoid ``n`` (together with the 246 | function ``q``) that satisfies the above factorization property. 247 | 248 | Incidentally, this answers our second question. The function ``U h`` is 249 | the one that has the power to collapse multiple elements of ``U m`` to a 250 | single element of ``U n``. This collapse corresponds to identifying some 251 | elements of the free monoid. Therefore any monoid with generators ``x`` 252 | can be obtained from the free monoid based on ``x`` by identifying some 253 | of the elements. The free monoid is the one where only the bare minimum 254 | of identifications have been made. 255 | 256 | We’ll come back to free monoids when we talk about adjunctions. 257 | 258 | Challenges 259 | ========== 260 | 261 | #. You might think (as I did, originally) that the requirement that a 262 | homomorphism of monoids preserve the unit is redundant. After all, we 263 | know that for all ``a`` 264 | 265 | .. code-block:: haskell 266 | 267 | h a * h e = h (a * e) = h a 268 | 269 | So ``h e`` acts like a right unit (and, by analogy, as a left unit). 270 | The problem is that ``h a``, for all ``a`` might only cover a 271 | sub-monoid of the target monoid. There may be a “true” unit outside 272 | of the image of ``h``. Show that an isomorphism between monoids that 273 | preserves multiplication must automatically preserve unit. 274 | 275 | #. Consider a monoid homomorphism from lists of integers with 276 | concatenation to integers with multiplication. What is the image of 277 | the empty list ``[]``? Assume that all singleton lists are mapped to 278 | the integers they contain, that is ``[3]`` is mapped to 3, etc. 279 | What’s the image of ``[1, 2, 3, 4]``? How many different lists map to 280 | the integer 12? Is there any other homomorphism between the two 281 | monoids? 282 | #. What is the free monoid generated by a one-element set? Can you see 283 | what it’s isomorphic to? 284 | 285 | Acknowledgments 286 | =============== 287 | 288 | I’d like to thank Gershom Bazerman for checking my math and logic, and André van 289 | Meulebrouck, who has been volunteering his editing help throughout this series 290 | of posts. 291 | 292 | .. |Bunnies| image:: ../images/2015/07/bunnies.jpg 293 | :class: alignnone wp-image-4840 294 | :width: 436px 295 | :height: 201px 296 | :target: ../images/2015/07/bunnies.jpg 297 | .. |Monoid Pattern| image:: ../images/2015/07/monoid-pattern.jpg 298 | :class: alignnone size-medium wp-image-4841 299 | :width: 300px 300 | :height: 185px 301 | :target: ../images/2015/07/monoid-pattern.jpg 302 | .. |Monoid Ranking| image:: ../images/2015/07/monoid-ranking.jpg 303 | :class: alignnone size-medium wp-image-4842 304 | :width: 300px 305 | :height: 221px 306 | :target: ../images/2015/07/monoid-ranking.jpg 307 | -------------------------------------------------------------------------------- /src/part2/15-the-yoneda-lemma.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | The Yoneda Lemma 3 | ================ 4 | 5 | Most constructions in category theory are generalizations of results 6 | from other more specific areas of mathematics. Things like products, 7 | coproducts, monoids, exponentials, etc., have been known long before 8 | category theory. They might have been known under different names in 9 | different branches of mathematics. A cartesian product in set theory, a 10 | meet in order theory, a conjunction in logic — they are all specific 11 | examples of the abstract idea of a categorical product. 12 | 13 | The Yoneda lemma stands out in this respect as a sweeping statement 14 | about categories in general with little or no precedent in other 15 | branches of mathematics. Some say that its closest analog is Cayley’s 16 | theorem in group theory (every group is isomorphic to a permutation 17 | group of some set). 18 | 19 | The setting for the Yoneda lemma is an arbitrary category *C* together 20 | with a functor ``F`` from *C* to **Set**. We’ve seen in the previous 21 | section that some **Set**-valued functors are representable, that is 22 | isomorphic to a hom-functor. The Yoneda lemma tells us that all 23 | **Set**-valued functors can be obtained from hom-functors through 24 | natural transformations, and it explicitly enumerates all such 25 | transformations. 26 | 27 | When I talked about natural transformations, I mentioned that the 28 | naturality condition can be quite restrictive. When you define a 29 | component of a natural transformation at one object, naturality may be 30 | strong enough to “transport” this component to another object that is 31 | connected to it through a morphism. The more arrows between objects in 32 | the source and the target categories there are, the more constraints you 33 | have for transporting the components of natural transformations. **Set** 34 | happens to be a very arrow-rich category. 35 | 36 | The Yoneda lemma tells us that a natural transformation between a 37 | hom-functor and any other functor ``F`` is completely determined by 38 | specifying the value of its single component at just one point! The rest 39 | of the natural transformation just follows from naturality conditions. 40 | 41 | So let’s review the naturality condition between the two functors 42 | involved in the Yoneda lemma. The first functor is the hom-functor. It 43 | maps any object ``x`` in *C* to the set of morphisms ``C(a, x)`` — for 44 | ``a`` a fixed object in *C*. We’ve also seen that it maps any morphism 45 | ``f`` from ``x`` to ``y`` to ``C(a, f)``. 46 | 47 | The second functor is an arbitrary **Set**-valued functor ``F``. 48 | 49 | Let’s call the natural transformation between these two functors ``α``. 50 | Because we are operating in **Set**, the components of the natural 51 | transformation, like ``αx`` or ``αy``, are just regular functions 52 | between sets: 53 | 54 | .. code-block:: haskell 55 | 56 | αx :: C(a, x) -> F x 57 | αy :: C(a, y) -> F y 58 | 59 | |Yoneda1| 60 | 61 | And because these are just functions, we can look at their values at 62 | specific points. But what’s a point in the set ``C(a, x)``? Here’s the 63 | key observation: Every point in the set ``C(a, x)`` is also a morphism 64 | ``h`` from ``a`` to ``x``. 65 | 66 | So the naturality square for ``α``: 67 | 68 | :: 69 | 70 | αy ∘ C(a, f) = F f ∘ αx 71 | 72 | becomes, point-wise, when acting on ``h``: 73 | 74 | .. code-block:: haskell 75 | 76 | αy (C(a, f) h) = (F f) (αx h) 77 | 78 | You might recall from the previous section that the action of the 79 | hom-functor ``C(a,-)`` on a morphism ``f`` was defined as 80 | precomposition: 81 | 82 | :: 83 | 84 | C(a, f) h = f ∘ h 85 | 86 | which leads to: 87 | 88 | :: 89 | 90 | αy (f ∘ h) = (F f) (αx h) 91 | 92 | Just how strong this condition is can be seen by specializing it to the 93 | case of ``x`` equal to ``a``. 94 | 95 | |Yoneda2| 96 | 97 | In that case ``h`` becomes a morphism from ``a`` to ``a``. We know that 98 | there is at least one such morphism, ``h = ida``. Let’s plug it in: 99 | 100 | .. code-block:: haskell 101 | 102 | αy f = (F f) (αa ida) 103 | 104 | Notice what has just happened: The left hand side is the action of 105 | ``αy`` on an arbitrary element ``f`` of ``C(a, y)``. And it is totally 106 | determined by the single value of ``αa`` at ``ida``. We can pick any 107 | such value and it will generate a natural transformation. Since the 108 | values of ``αa`` are in the set ``F a``, any point in ``F a`` will 109 | define some ``α``. 110 | 111 | Conversely, given any natural transformation ``α`` from ``C(a, -)`` to 112 | ``F``, you can evaluate it at ``ida`` to get a point in ``F a``. 113 | 114 | We have just proven the Yoneda lemma: 115 | 116 | There is a one-to-one correspondence between natural transformations 117 | from ``C(a, -)`` to ``F`` and elements of ``F a``. 118 | 119 | in other words, 120 | 121 | :: 122 | 123 | Nat(C(a, -), F) ≅ F a 124 | 125 | Or, if we use the notation ``[C, Set]`` for the functor category between 126 | *C* and **Set**, the set of natural transformation is just a hom-set in 127 | that category, and we can write: 128 | 129 | :: 130 | 131 | [C, Set](C(a, -), F) ≅ F a 132 | 133 | I’ll explain later how this correspondence is in fact a natural 134 | isomorphism. 135 | 136 | Now let’s try to get some intuition about this result. The most amazing 137 | thing is that the whole natural transformation crystallizes from just 138 | one nucleation site: the value we assign to it at ``ida``. It spreads 139 | from that point following the naturality condition. It floods the image 140 | of *C* in **Set**. So let’s first consider what the image of *C* is 141 | under ``C(a, -)``. 142 | 143 | Let’s start with the image of ``a`` itself. Under the hom-functor 144 | ``C(a, -)``, ``a`` is mapped to the set ``C(a, a)``. Under the functor 145 | ``F``, on the other hand, it is mapped to the set ``F a``. The component 146 | of the natural transformation ``αa`` is some function from ``C(a, a)`` 147 | to ``F a``. Let’s focus on just one point in the set ``C(a, a)``, the 148 | point corresponding to the morphism ``ida``. To emphasize the fact that 149 | it’s just a point in a set, let’s call it ``p``. The component ``αa`` 150 | should map ``p`` to some point ``q`` in ``F a``. I’ll show you that any 151 | choice of ``q`` leads to a unique natural transformation. 152 | 153 | |Yoneda3| 154 | 155 | The first claim is that the choice of one point ``q`` uniquely 156 | determines the rest of the function ``αa``. Indeed, let’s pick any other 157 | point, ``p'`` in ``C(a, a)``, corresponding to some morphism ``g`` from 158 | ``a`` to ``a``. And here’s where the magic of the Yoneda lemma happens: 159 | ``g`` can be viewed as a point ``p'`` in the set ``C(a, a)``. At the 160 | same time, it selects two *functions* between sets. Indeed, under the 161 | hom-functor, the morphism ``g`` is mapped to a function ``C(a, g)``; and 162 | under ``F`` it’s mapped to ``F g``. 163 | 164 | |Yoneda4| 165 | 166 | Now let’s consider the action of ``C(a, g)`` on our original ``p`` 167 | which, as you remember, corresponds to ``ida``. It is defined as 168 | precomposition, ``g∘ida``, which is equal to ``g``, which corresponds to 169 | our point ``p'``. So the morphism ``g`` is mapped to a function that, 170 | when acting on ``p`` produces ``p'``, which is ``g``. We have come full 171 | circle! 172 | 173 | Now consider the action of ``F g`` on ``q``. It is some ``q'``, a point 174 | in ``F a``. To complete the naturality square, ``p'`` must be mapped to 175 | ``q'`` under ``αa``. We picked an arbitrary ``p'`` (an arbitrary ``g``) 176 | and derived its mapping under ``αa``. The function ``αa`` is thus 177 | completely determined. 178 | 179 | The second claim is that ``αx`` is uniquely determined for any object 180 | ``x`` in *C* that is connected to ``a``. The reasoning is analogous, 181 | except that now we have two more sets, ``C(a, x)`` and ``F x``, and the 182 | morphism ``g`` from ``a`` to ``x`` is mapped, under the hom-functor, to: 183 | 184 | .. code-block:: haskell 185 | 186 | C(a, g) :: C(a, a) -> C(a, x) 187 | 188 | and under ``F`` to: 189 | 190 | .. code-block:: haskell 191 | 192 | F g :: F a -> F x 193 | 194 | Again, ``C(a, g)`` acting on our ``p`` is given by the precomposition: 195 | ``g ∘ ida``, which corresponds to a point ``p'`` in ``C(a, x)``. 196 | Naturality determines the value of ``αx`` acting on ``p'`` to be: 197 | 198 | .. code-block:: haskell 199 | 200 | q' = (F g) q 201 | 202 | Since ``p'`` was arbitrary, the whole function ``αx`` is thus 203 | determined. 204 | 205 | |Yoneda5| 206 | 207 | What if there are objects in *C* that have no connection to ``a``? They 208 | are all mapped under ``C(a, -)`` to a single set — the empty set. Recall 209 | that the empty set is the initial object in the category of sets. It 210 | means that there is a unique function from this set to any other set. We 211 | called this function ``absurd``. So here, again, we have no choice for 212 | the component of the natural transformation: it can only be ``absurd``. 213 | 214 | One way of understanding the Yoneda lemma is to realize that natural 215 | transformations between **Set**-valued functors are just families of 216 | functions, and functions are in general lossy. A function may collapse 217 | information and it may cover only parts of its codomain. The only 218 | functions that are not lossy are the ones that are invertible — the 219 | isomorphisms. It follows then that the best structure-preserving 220 | **Set**-valued functors are the representable ones. They are either the 221 | hom-functors or the functors that are naturally isomorphic to 222 | hom-functors. Any other functor ``F`` is obtained from a hom-functor 223 | through a lossy transformation. Such a transformation may not only lose 224 | information, but it may also cover only a small part of the image of the 225 | functor ``F`` in **Set**. 226 | 227 | Yoneda in Haskell 228 | ================= 229 | 230 | We have already encountered the hom-functor in Haskell under the guise 231 | of the reader functor: 232 | 233 | .. code-block:: haskell 234 | 235 | type Reader a x = a -> x 236 | 237 | The reader maps morphisms (here, functions) by precomposition: 238 | 239 | .. code-block:: haskell 240 | 241 | instance Functor (Reader a) where 242 | fmap f h = f . h 243 | 244 | The Yoneda lemma tells us that the reader functor can be naturally 245 | mapped to any other functor. 246 | 247 | A natural transformation is a polymorphic function. So given a functor 248 | ``F``, we have a mapping to it from the reader functor: 249 | 250 | .. code-block:: haskell 251 | 252 | alpha :: forall x . (a -> x) -> F x 253 | 254 | As usual, ``forall`` is optional, but I like to write it explicitly to 255 | emphasize parametric polymorphism of natural transformations. 256 | 257 | The Yoneda lemma tells us that these natural transformations are in 258 | one-to-one correspondence with the elements of ``F a``: 259 | 260 | :: 261 | 262 | forall x . (a -> x) -> F x ≅ F a 263 | 264 | The right hand side of this identity is what we would normally consider 265 | a data structure. Remember the interpretation of functors as generalized 266 | containers? ``F a`` is a container of ``a``. But the left hand side is a 267 | polymorphic function that takes a function as an argument. The Yoneda 268 | lemma tells us that the two representations are equivalent — they 269 | contain the same information. 270 | 271 | Another way of saying this is: Give me a polymorphic function of the 272 | type: 273 | 274 | .. code-block:: haskell 275 | 276 | alpha :: forall x . (a -> x) -> F x 277 | 278 | and I’ll produce a container of ``a``. The trick is the one we used in 279 | the proof of the Yoneda lemma: we call this function with ``id`` to get 280 | an element of ``F a``: 281 | 282 | .. code-block:: haskell 283 | 284 | alpha id :: F a 285 | 286 | The converse is also true: Given a value of the type ``F a``: 287 | 288 | .. code-block:: haskell 289 | 290 | fa :: F a 291 | 292 | one can define a polymorphic function: 293 | 294 | .. code-block:: haskell 295 | 296 | alpha h = fmap h fa 297 | 298 | of the correct type. You can easily go back and forth between the two 299 | representations. 300 | 301 | The advantage of having multiple representations is that one might be 302 | easier to compose than the other, or that one might be more efficient in 303 | some applications than the other. 304 | 305 | The simplest illustration of this principle is the code transformation 306 | that is often used in compiler construction: the continuation passing 307 | style or CPS. It’s the simplest application of the Yoneda lemma to the 308 | identity functor. Replacing ``F`` with identity produces: 309 | 310 | :: 311 | 312 | forall r . (a -> r) -> r ≅ a 313 | 314 | The interpretation of this formula is that any type ``a`` can be 315 | replaced by a function that takes a “handler” for ``a``. A handler is a 316 | function accepting ``a`` and performing the rest of the computation — 317 | the continuation. (The type ``r`` usually encapsulates some kind of 318 | status code.) 319 | 320 | This style of programming is very common in UIs, in asynchronous 321 | systems, and in concurrent programming. The drawback of CPS is that it 322 | involves inversion of control. The code is split between producers and 323 | consumers (handlers), and is not easily composable. Anybody who’s done 324 | any amount of nontrivial web programming is familiar with the nightmare 325 | of spaghetti code from interacting stateful handlers. As we’ll see 326 | later, judicious use of functors and monads can restore some 327 | compositional properties of CPS. 328 | 329 | Co-Yoneda 330 | ========= 331 | 332 | As usual, we get a bonus construction by inverting the direction of 333 | arrows. The Yoneda lemma can be applied to the opposite category 334 | *C*\ :sup:`op` to give us a mapping between contravariant functors. 335 | 336 | Equivalently, we can derive the co-Yoneda lemma by fixing the target 337 | object of our hom-functors instead of the source. We get the 338 | contravariant hom-functor from *C* to **Set**: ``C(-, a)``. The 339 | contravariant version of the Yoneda lemma establishes one-to-one 340 | correspondence between natural transformations from this functor to any 341 | other contravariant functor ``F`` and the elements of the set ``F a``: 342 | 343 | :: 344 | 345 | Nat(C(-, a), F) ≅ F a 346 | 347 | Here’s the Haskell version of the co-Yoneda lemma: 348 | 349 | :: 350 | 351 | forall x . (x -> a) -> F x ≅ F a 352 | 353 | Notice that in some literature it’s the contravariant version that’s 354 | called the Yoneda lemma. 355 | 356 | Challenges 357 | ========== 358 | 359 | #. Show that the two functions ``phi`` and ``psi`` that form the Yoneda 360 | isomorphism in Haskell are inverses of each other. 361 | 362 | .. code-block:: haskell 363 | 364 | phi :: (forall x . (a -> x) -> F x) -> F a 365 | phi alpha = alpha id 366 | 367 | .. code-block:: haskell 368 | 369 | psi :: F a -> (forall x . (a -> x) -> F x) 370 | psi fa h = fmap h fa 371 | 372 | #. A discrete category is one that has objects but no morphisms other 373 | than identity morphisms. How does the Yoneda lemma work for functors 374 | from such a category? 375 | #. A list of units ``[()]`` contains no other information but its 376 | length. So, as a data type, it can be considered an encoding of 377 | integers. An empty list encodes zero, a singleton ``[()]`` (a value, 378 | not a type) encodes one, and so on. Construct another representation 379 | of this data type using the Yoneda lemma for the list functor. 380 | 381 | Bibliography 382 | ============ 383 | 384 | #. `Catsters `__ video 385 | 386 | Acknowledgments 387 | =============== 388 | 389 | I’d like to thank Gershom Bazerman for checking my math and logic, and André van 390 | Meulebrouck, who has been volunteering his editing help throughout this series 391 | of posts. 392 | 393 | .. |Yoneda1| image:: ../images/2015/08/yoneda1-e1440290035365.png 394 | :class: alignnone wp-image-4983 395 | :width: 263px 396 | :height: 259px 397 | :target: ../images/2015/08/yoneda1.png 398 | .. |Yoneda2| image:: ../images/2015/08/yoneda2.png 399 | :class: alignnone size-medium wp-image-4987 400 | :width: 300px 401 | :height: 275px 402 | :target: ../images/2015/08/yoneda2.png 403 | .. |Yoneda3| image:: ../images/2015/09/yoneda3.png 404 | :class: alignnone wp-image-5217 size-full 405 | :target: ../images/2015/09/yoneda3.png 406 | .. |Yoneda4| image:: ../images/2015/09/yoneda4.png 407 | :class: alignnone wp-image-5218 size-full 408 | :target: ../images/2015/09/yoneda4.png 409 | .. |Yoneda5| image:: ../images/2015/09/yoneda5.png 410 | :class: alignnone wp-image-5219 size-full 411 | :target: ../images/2015/09/yoneda5.png 412 | -------------------------------------------------------------------------------- /src/part2/16-yoneda-embedding.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Yoneda Embedding 3 | ================ 4 | 5 | We’ve seen previously that, when we fix an object ``a`` in the category 6 | *C*, the mapping ``C(a, -)`` is a (covariant) functor from *C* to 7 | **Set**. 8 | 9 | .. code-block:: haskell 10 | 11 | x -> C(a, x) 12 | 13 | (The codomain is **Set** because the hom-set C(a, x) is a *set*.) We 14 | call this mapping a hom-functor — we have previously defined its action 15 | on morphisms as well. 16 | 17 | Now let’s vary ``a`` in this mapping. We get a new mapping that assigns 18 | the hom-\ *functor* ``C(a, -)`` to any ``a``. 19 | 20 | .. code-block:: haskell 21 | 22 | a -> C(a, -) 23 | 24 | It’s a mapping of objects from category *C* to functors, which are 25 | *objects* in the functor category (see the section about functor 26 | categories in :doc:`Natural 27 | Transformations <../part1/10-natural-transformations>`). 28 | Let’s use the notation ``[C, Set]`` for the functor category from *C* to 29 | **Set**. You may also recall that hom-functors are the prototypical 30 | :doc:`representable 31 | functors <../part2/14-representable-functors>`. 32 | 33 | Every time we have a mapping of objects between two categories, it’s 34 | natural to ask if such a mapping is also a functor. In other words 35 | whether we can lift a morphism from one category to a morphism in the 36 | other category. A morphism in *C* is just an element of ``C(a, b)``, but 37 | a morphism in the functor category ``[C, Set]`` is a natural 38 | transformation. So we are looking for a mapping of morphisms to natural 39 | transformations. 40 | 41 | Let’s see if we can find a natural transformation corresponding to a 42 | morphism ``f :: a->b``. First, lets see what ``a`` and ``b`` are mapped 43 | to. They are mapped to two functors: ``C(a, -)`` and ``C(b, -)``. We 44 | need a natural transformation between those two functors. 45 | 46 | And here’s the trick: we use the Yoneda lemma: 47 | 48 | :: 49 | 50 | [C, Set](C(a, -), F) ≅ F a 51 | 52 | and replace the generic ``F`` with the hom-functor ``C(b, -)``. We get: 53 | 54 | :: 55 | 56 | [C, Set](C(a, -), C(b, -)) ≅ C(b, a) 57 | 58 | |Yoneda Embedding| 59 | 60 | This is exactly the natural transformation between the two hom-functors 61 | we were looking for, but with a little twist: We have a mapping between 62 | a natural transformation and a morphism — an element of ``C(b, a)`` — 63 | that goes in the “wrong” direction. But that’s okay; it only means that 64 | the functor we are looking at is contravariant. 65 | 66 | |Yoneda Embedding 2| 67 | 68 | Actually, we’ve got even more than we bargained for. The mapping from 69 | *C* to ``[C, Set]`` is not only a contravariant functor — it is a *fully 70 | faithful* functor. Fullness and faithfulness are properties of functors 71 | that describe how they map hom-sets. 72 | 73 | A *faithful* functor is *injective* on hom-sets, meaning that it maps 74 | distinct morphisms to distinct morphisms. In other words, it doesn’t 75 | coalesce them. 76 | 77 | A *full* functor is *surjective* on hom-sets, meaning that it maps one 78 | hom-set *onto* the other hom-set, fully covering the latter. 79 | 80 | A fully faithful functor ``F`` is a *bijection* on hom-sets — a one to 81 | one matching of all elements of both sets. For every pair of objects 82 | ``a`` and ``b`` in the source category *C* there is a bijection between 83 | ``C(a, b)`` and ``D(F a, F b)``, where *D* is the target category of 84 | ``F`` (in our case, the functor category, ``[C, Set]``). Notice that 85 | this doesn’t mean that ``F`` is a bijection on *objects*. There may be 86 | objects in *D* that are not in the image of ``F``, and we can’t say 87 | anything about hom-sets for those objects. 88 | 89 | The Embedding 90 | ============= 91 | 92 | The (contravariant) functor we have just described, the functor that 93 | maps objects in *C* to functors in ``[C, Set]``: 94 | 95 | .. code-block:: haskell 96 | 97 | a -> C(a, -) 98 | 99 | defines the *Yoneda embedding*. It *embeds* a category *C* (strictly 100 | speaking, the category *C\ :sup:`op`*, because of contravariance) inside 101 | the functor category ``[C, Set]``. It not only maps objects in *C* to 102 | functors, but also faithfully preserves all connections between them. 103 | 104 | This is a very useful result because mathematicians know a lot about the 105 | category of functors, especially functors whose codomain is **Set**. We 106 | can get a lot of insight about an arbitrary category *C* by embedding it 107 | in the functor category. 108 | 109 | Of course there is a dual version of the Yoneda embedding, sometimes 110 | called the co-Yoneda embedding. Observe that we could have started by 111 | fixing the target object (rather than the source object) of each 112 | hom-set, ``C(-, a)``. That would give us a contravariant hom-functor. 113 | Contravariant functors from *C* to **Set** are our familiar presheaves 114 | (see, for instance, :doc:`Limits and 115 | Colimits <../part2/12-limits-and-colimits>`). 116 | The co-Yoneda embedding defines the embedding of a category *C* in the 117 | category of presheaves. Its action on morphisms is given by: 118 | 119 | :: 120 | 121 | [C, Set](C(-, a), C(-, b)) ≅ C(a, b) 122 | 123 | Again, mathematicians know a lot about the category of presheaves, so 124 | being able to embed an arbitrary category in it is a big win. 125 | 126 | Application to Haskell 127 | ====================== 128 | 129 | In Haskell, the Yoneda embedding can be represented as the isomorphism 130 | between natural transformations amongst reader functors on the one hand, 131 | and functions (going in the opposite direction) on the other hand: 132 | 133 | :: 134 | 135 | forall x. (a -> x) -> (b -> x) ≅ b -> a 136 | 137 | (Remember, the reader functor is equivalent to ``((->) a)``.) 138 | 139 | The left hand side of this identity is a polymorphic function that, 140 | given a function from ``a`` to ``x`` and a value of type ``b``, can 141 | produce a value of type ``x`` (I’m uncurrying — dropping the parentheses 142 | around — the function ``b -> x``). The only way this can be done for all 143 | ``x`` is if our function knows how to convert a ``b`` to an ``a``. It 144 | has to secretly have access to a function ``b->a``. 145 | 146 | Given such a converter, ``btoa``, one can define the left hand side, 147 | call it\ ``fromY``, as: 148 | 149 | .. code-block:: haskell 150 | 151 | fromY :: (a -> x) -> b -> x 152 | fromY f b = f (btoa b) 153 | 154 | Conversely, given a function ``fromY`` we can recover the converter by 155 | calling ``fromY`` with the identity: 156 | 157 | .. code-block:: haskell 158 | 159 | fromY id :: b -> a 160 | 161 | This establishes the bijection between functions of the type ``fromY`` 162 | and ``btoa``. 163 | 164 | An alternative way of looking at this isomorphism is that it’s a CPS 165 | encoding of a function from ``b`` to ``a``. The argument ``a->x`` is a 166 | continuation (the handler). The result is a function from ``b`` to ``x`` 167 | which, when called with a value of type ``b``, will execute the 168 | continuation precomposed with the function being encoded. 169 | 170 | The Yoneda embedding also explains some of the alternative 171 | representations of data structures in Haskell. In particular, it 172 | provides a very useful `representation of 173 | lenses `__ 174 | from the ``Control.Lens`` library. 175 | 176 | Preorder Example 177 | ================ 178 | 179 | This example was suggested by Robert Harper. It’s the application of the 180 | Yoneda embedding to a category defined by a preorder. A preorder is a 181 | set with an ordering relation between its elements that’s traditionally 182 | written as ``<=`` (less than or equal). The “pre” in preorder is there 183 | because we’re only requiring the relation to be transitive and reflexive 184 | but not necessarily antisymmetric (so it’s possible to have cycles). 185 | 186 | A set with the preorder relation gives rise to a category. The objects 187 | are the elements of this set. A morphism from object ``a`` to ``b`` 188 | either doesn’t exist, if the objects cannot be compared or if it’s not 189 | true that ``a <= b``; or it exists if ``a <= b``, and it points from 190 | ``a`` to ``b``. There is never more than one morphism from one object to 191 | another. Therefore any hom-set in such a category is either an empty set 192 | or a one-element set. Such a category is called *thin*. 193 | 194 | It’s easy to convince yourself that this construction is indeed a 195 | category: The arrows are composable because, if ``a <= b`` and 196 | ``b <= c`` then ``a <= c``; and the composition is associative. We also 197 | have the identity arrows because every element is (less than or) equal 198 | to itself (reflexivity of the underlying relation). 199 | 200 | We can now apply the co-Yoneda embedding to a preorder category. In 201 | particular, we’re interested in its action on morphisms: 202 | 203 | :: 204 | 205 | [C, Set](C(-, a), C(-, b)) ≅ C(a, b) 206 | 207 | The hom-set on the right hand side is non-empty if and only if 208 | ``a <= b`` — in which case it’s a one-element set. Consequently, if 209 | ``a <= b``, there exists a single natural transformation on the left. 210 | Otherwise there is no natural transformation. 211 | 212 | So what’s a natural transformation between hom-functors in a preorder? 213 | It should be a family of functions between sets ``C(-, a)`` and 214 | ``C(-, b)``. In a preorder, each of these sets can either be empty or a 215 | singleton. Let’s see what kind of functions are there at our disposal. 216 | 217 | There is a function from an empty set to itself (the identity acting on 218 | an empty set), a function ``absurd`` from an empty set to a singleton 219 | set (it does nothing, since it only needs to be defined for elements of 220 | an empty set, of which there are none), and a function from a singleton 221 | to itself (the identity acting on a one-element set). The only 222 | combination that is forbidden is the mapping from a singleton to an 223 | empty set (what would the value of such a function be when acting on the 224 | single element?). 225 | 226 | So our natural transformation will never connect a singleton hom-set to 227 | an empty hom-set. In other words, if ``x <= a`` (singleton hom-set 228 | ``C(x, a)``) then ``C(x, b)`` cannot be empty. A non-empty ``C(x, b)`` 229 | means that ``x`` is less or equal to ``b``. So the existence of the 230 | natural transformation in question requires that, for every ``x``, if 231 | ``x <= a`` then ``x <= b``. 232 | 233 | :: 234 | 235 | for all x, x ≤ a ⇒ x ≤ b 236 | 237 | On the other hand, co-Yoneda tells us that the existence of this natural 238 | transformation is equivalent to ``C(a, b)`` being non-empty, or to 239 | ``a <= b``. Together, we get: 240 | 241 | :: 242 | 243 | a ≤ b if and only if for all x, x ≤ a ⇒ x ≤ b 244 | 245 | We could have arrived at this result directly. The intuition is that, if 246 | ``a <= b`` then all elements that are below ``a`` must also be below 247 | ``b``. Conversely, when you substitute ``a`` for ``x`` on the right hand 248 | side, it follows that ``a <= b``. But you must admit that arriving at 249 | this result through the Yoneda embedding is much more exciting. 250 | 251 | Naturality 252 | ========== 253 | 254 | The Yoneda lemma establishes the isomorphism between the set of natural 255 | transformations and an object in **Set**. Natural transformations are 256 | morphisms in the functor category ``[C, Set]``. The set of natural 257 | transformation between any two functors is a hom-set in that category. 258 | The Yoneda lemma is the isomorphism: 259 | 260 | :: 261 | 262 | [C, Set](C(a, -), F) ≅ F a 263 | 264 | This isomorphism turns out to be natural in both ``F`` and ``a``. In 265 | other words, it’s natural in ``(F, a)``, a pair taken from the product 266 | category ``[C, Set] × C``. Notice that we are now treating ``F`` as an 267 | *object* in the functor category. 268 | 269 | Let’s think for a moment what this means. A natural isomorphism is an 270 | invertible *natural transformation* between two functors. And indeed, 271 | the right hand side of our isomorphism is a functor. It’s a functor from 272 | ``[C, Set] × C`` to **Set**. Its action on a pair ``(F, a)`` is a set — 273 | the result of evaluating the functor ``F`` at the object ``a``. This is 274 | called the evaluation functor. 275 | 276 | The left hand side is also a functor that takes ``(F, a)`` to a set of 277 | natural transformations ``[C, Set](C(a, -), F)``. 278 | 279 | To show that these are really functors, we should also define their 280 | action on morphisms. But what’s a morphism between a pair ``(F, a)`` and 281 | ``(G, b)``? It’s a pair of morphisms, ``(Φ, f)``; the first being a 282 | morphism between functors — a natural transformation — the second being 283 | a regular morphism in *C*. 284 | 285 | The evaluation functor takes this pair ``(Φ, f)`` and maps it to a 286 | function between two sets, ``F a`` and ``G b``. We can easily construct 287 | such a function from the component of ``Φ`` at ``a`` (which maps ``F a`` 288 | to ``G a``) and the morphism ``f`` lifted by ``G``: 289 | 290 | :: 291 | 292 | (G f) ∘ Φa 293 | 294 | Notice that, because of naturality of ``Φ``, this is the same as: 295 | 296 | :: 297 | 298 | Φb ∘ (F f) 299 | 300 | I’m not going to prove the naturality of the whole isomorphism — after 301 | you’ve established what the functors are, the proof is pretty 302 | mechanical. It follows from the fact that our isomorphism is built up 303 | from functors and natural transformations. There is simply no way for it 304 | to go wrong. 305 | 306 | Challenges 307 | ========== 308 | 309 | #. Express the co-Yoneda embedding in Haskell. 310 | #. Show that the bijection we established between ``fromY`` and ``btoa`` 311 | is an isomorphism (the two mappings are the inverse of each other). 312 | #. Work out the Yoneda embedding for a monoid. What functor corresponds 313 | to the monoid’s single object? What natural transformations 314 | correspond to monoid morphisms? 315 | #. What is the application of the *covariant* Yoneda embedding to 316 | preorders? (Question suggested by Gershom Bazerman.) 317 | #. Yoneda embedding can be used to embed an arbitrary functor category 318 | ``[C, D]`` in the functor category ``[[C, D], Set]``. Figure out how 319 | it works on morphisms (which in this case are natural 320 | transformations). 321 | 322 | Acknowledgments 323 | =============== 324 | 325 | I’d like to thank Gershom Bazerman for checking my math and logic. 326 | 327 | .. |Yoneda Embedding| image:: ../images/2015/07/yoneda-embedding.jpg 328 | :class: alignnone wp-image-4782 329 | :width: 372px 330 | :height: 180px 331 | :target: ../images/2015/07/yoneda-embedding.jpg 332 | .. |Yoneda Embedding 2| image:: ../images/2015/07/yoneda-embedding-2.jpg 333 | :class: alignnone wp-image-4783 334 | :width: 433px 335 | :height: 157px 336 | :target: ../images/2015/07/yoneda-embedding-2.jpg 337 | -------------------------------------------------------------------------------- /src/part3/17-its-all-about-morphisms.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | It’s All About Morphisms 3 | ======================== 4 | 5 | If I haven’t convinced you yet that category theory is all about 6 | morphisms then I haven’t done my job properly. Since the next topic is 7 | adjunctions, which are defined in terms of isomorphisms of hom-sets, it 8 | makes sense to review our intuitions about the building blocks of 9 | hom-sets. Also, you’ll see that adjunctions provide a more general 10 | language to describe a lot of constructions we’ve studied before, so it 11 | might help to review them too. 12 | 13 | Functors 14 | ======== 15 | 16 | To begin with, you should really think of functors as mappings of 17 | morphisms — the view that’s emphasized in the Haskell definition of the 18 | ``Functor`` typeclass, which revolves around ``fmap``. Of course, 19 | functors also map objects — the endpoints of morphisms — otherwise we 20 | wouldn’t be able to talk about preserving composition. Objects tell us 21 | which pairs of morphisms are composable. The target of one morphism must 22 | be equal to the source of the other — if they are to be composed. So if 23 | we want the composition of morphisms to be mapped to the composition of 24 | *lifted* morphisms, the mapping of their endpoints is pretty much 25 | determined. 26 | 27 | Commuting Diagrams 28 | ================== 29 | 30 | A lot of properties of morphisms are expressed in terms of commuting 31 | diagrams. If a particular morphism can be described as a composition of 32 | other morphisms in more than one way, then we have a commuting diagram. 33 | 34 | In particular, commuting diagrams form the basis of almost all universal 35 | constructions (with the notable exceptions of the initial and terminal 36 | objects). We’ve seen this in the definitions of products, coproducts, 37 | various other (co-)limits, exponential objects, free monoids, etc. 38 | 39 | The product is a simple example of a universal construction. We pick two 40 | objects ``a`` and ``b`` and see if there exists an object ``c``, 41 | together with a pair of morphisms ``p`` and ``q``, that has the 42 | universal property of being their product. 43 | 44 | |ProductRanking| 45 | 46 | A product is a special case of a limit. A limit is defined in terms of 47 | cones. A general cone is built from commuting diagrams. Commutativity of 48 | those diagrams may be replaced with a suitable naturality condition for 49 | the mapping of functors. This way commutativity is reduced to the role 50 | of the assembly language for the higher level language of natural 51 | transformations. 52 | 53 | Natural Transformations 54 | ======================= 55 | 56 | In general, natural transformations are very convenient whenever we need 57 | a mapping from morphisms to commuting squares. Two opposing sides of a 58 | naturality square are the mappings of some morphism ``f`` under two 59 | functors ``F`` and ``G``. The other sides are the components of the 60 | natural transformation (which are also morphisms). 61 | 62 | |3_Naturality| 63 | 64 | Naturality means that when you move to the “neighboring” component (by 65 | neighboring I mean connected by a morphism), you’re not going against 66 | the structure of either the category or the functors. It doesn’t matter 67 | whether you first use a component of the natural transformation to 68 | bridge the gap between objects, and then jump to its neighbor using the 69 | functor; or the other way around. The two directions are orthogonal. A 70 | natural transformation moves you left and right, and the functors move 71 | you up and down or back and forth — so to speak. You can visualize the 72 | *image* of a functor as a sheet in the target category. A natural 73 | transformation maps one such sheet corresponding to F, to another, 74 | corresponding to G. 75 | 76 | |Sheets| 77 | 78 | We’ve seen examples of this orthogonality in Haskell. There the action 79 | of a functor modifies the content of a container without changing its 80 | shape, while a natural transformation repackages the untouched contents 81 | into a different container. The order of these operations doesn’t 82 | matter. 83 | 84 | We’ve seen the cones in the definition of a limit replaced by natural 85 | transformations. Naturality ensures that the sides of every cone 86 | commute. Still, a limit is defined in terms of mappings *between* cones. 87 | These mappings must also satisfy commutativity conditions. (For 88 | instance, the triangles in the definition of the product must commute.) 89 | 90 | These conditions, too, may be replaced by naturality. You may recall 91 | that the *universal* cone, or the limit, is defined as a natural 92 | transformation between the (contravariant) hom-functor: 93 | 94 | .. code-block:: haskell 95 | 96 | F :: c -> C(c, Lim D) 97 | 98 | and the (also contravariant) functor that maps objects in *C* to cones, 99 | which themselves are natural transformations: 100 | 101 | .. code-block:: haskell 102 | 103 | G :: c -> Nat(Δc, D) 104 | 105 | Here, ``Δc`` is the constant functor, and ``D`` is the functor that 106 | defines the diagram in *C*. Both functors ``F`` and ``G`` have well 107 | defined actions on morphisms in *C*. It so happens that this particular 108 | natural transformation between ``F`` and ``G`` is an *isomorphism*. 109 | 110 | Natural Isomorphisms 111 | ==================== 112 | 113 | A natural isomorphism — which is a natural transformation whose every 114 | component is reversible — is category theory’s way of saying that “two 115 | things are the same.” A component of such a transformation must be an 116 | isomorphism between objects — a morphism that has the inverse. If you 117 | visualize functor images as sheets, a natural isomorphism is a 118 | one-to-one invertible mapping between those sheets. 119 | 120 | Hom-Sets 121 | ======== 122 | 123 | But what are morphisms? They do have more structure than objects: unlike 124 | objects, morphisms have two ends. But if you fix the source and the 125 | target objects, the morphisms between the two form a boring set (at 126 | least for locally small categories). We can give elements of this set 127 | names like ``f`` or ``g``, to distinguish one from another — but what is 128 | it, really, that makes them different? 129 | 130 | The essential difference between morphisms in a given hom-set lies in 131 | the way they compose with other morphisms (from abutting hom-sets). If 132 | there is a morphism ``h`` whose composition (either pre- or post-) with 133 | ``f`` is different than that with ``g``, for instance: 134 | 135 | :: 136 | 137 | h ∘ f ≠ h ∘ g 138 | 139 | then we can directly “observe” the difference between ``f`` and ``g``. 140 | But even if the difference is not directly observable, we might use 141 | functors to zoom in on the hom-set. A functor ``F`` may map the two 142 | morphisms to distinct morphisms: 143 | 144 | :: 145 | 146 | F f ≠ F g 147 | 148 | in a richer category, where the abutting hom-sets provide more 149 | resolution, e.g., 150 | 151 | :: 152 | 153 | h' ∘ F f ≠ h' ∘ F g 154 | 155 | where ``h'`` is not in the image of ``F``. 156 | 157 | Hom-Set Isomorphisms 158 | ==================== 159 | 160 | A lot of categorical constructions rely on isomorphisms between 161 | hom-sets. But since hom-sets are just sets, a plain isomorphism between 162 | them doesn’t tell you much. For finite sets, an isomorphism just says 163 | that they have the same number of elements. If the sets are infinite, 164 | their cardinality must be the same. But any meaningful isomorphism of 165 | hom-sets must take into account composition. And composition involves 166 | more than one hom-set. We need to define isomorphisms that span whole 167 | collections of hom-sets, and we need to impose some compatibility 168 | conditions that interoperate with composition. And a *natural* 169 | isomorphism fits the bill exactly. 170 | 171 | But what’s a natural isomorphism of hom-sets? Naturality is a property 172 | of mappings between functors, not sets. So we are really talking about a 173 | natural isomorphism between hom-set-valued functors. These functors are 174 | more than just set-valued functors. Their action on morphisms is induced 175 | by the appropriate hom-functors. Morphisms are canonically mapped by 176 | hom-functors using either pre- or post-composition (depending on the 177 | covariance of the functor). 178 | 179 | The Yoneda embedding is one example of such an isomorphism. It maps 180 | hom-sets in *C* to hom-sets in the functor category; and it’s natural. 181 | One functor in the Yoneda embedding is the hom-functor in *C* and the 182 | other maps objects to sets of natural transformations between hom-sets. 183 | 184 | The definition of a limit is also a natural isomorphism between hom-sets 185 | (the second one, again, in the functor category): 186 | 187 | :: 188 | 189 | C(c, Lim D) ≃ Nat(Δc, D) 190 | 191 | It turns out that our construction of an exponential object, or that of 192 | a free monoid, can also be rewritten as a natural isomorphism between 193 | hom-sets. 194 | 195 | This is no coincidence — we’ll see next that these are just different 196 | examples of adjunctions, which are defined as natural isomorphisms of 197 | hom-sets. 198 | 199 | Asymmetry of Hom-Sets 200 | ===================== 201 | 202 | There is one more observation that will help us understand adjunctions. 203 | Hom-sets are, in general, not symmetric. A hom-set ``C(a, b)`` is often 204 | very different from the hom-set ``C(b, a)``. The ultimate demonstration 205 | of this asymmetry is a partial order viewed as a category. In a partial 206 | order, a morphism from ``a`` to ``b`` exists if and only if ``a`` is 207 | less than or equal to ``b``. If ``a`` and ``b`` are different, then 208 | there can be no morphism going the other way, from ``b`` to ``a``. So if 209 | the hom-set ``C(a, b)`` is non-empty, which in this case means it’s a 210 | singleton set, then ``C(b, a)`` must be empty, unless ``a = b``. The 211 | arrows in this category have a definite flow in one direction. 212 | 213 | A preorder, which is based on a relation that’s not necessarily 214 | antisymmetric, is also “mostly” directional, except for occasional 215 | cycles. It’s convenient to think of an arbitrary category as a 216 | generalization of a preoder. 217 | 218 | A preorder is a thin category — all hom-sets are either singletons or 219 | empty. We can visualize a general category as a “thick” preorder. 220 | 221 | Challenges 222 | ========== 223 | 224 | #. Consider some degenerate cases of a naturality condition and draw the 225 | appropriate diagrams. For instance, what happens if either functor 226 | ``F`` or ``G`` map both objects ``a`` and ``b`` (the ends of 227 | ``f :: a -> b``) to the same object, e.g., ``F a = F b`` or 228 | ``G a = G b``? (Notice that you get a cone or a co-cone this way.) 229 | Then consider cases where either ``F a = G a`` or ``F b = G b``. 230 | Finally, what if you start with a morphism that loops on itself — 231 | ``f :: a -> a``? 232 | 233 | Acknowledgments 234 | =============== 235 | 236 | I’d like to thank Gershom Bazerman for checking my math and logic, and André van 237 | Meulebrouck, who has been volunteering his editing help throughout this series 238 | of posts. 239 | 240 | .. |ProductRanking| image:: ../images/2014/12/productranking.jpg 241 | :class: alignnone wp-image-3772 242 | :width: 171px 243 | :height: 139px 244 | :target: ../images/2014/12/productranking.jpg 245 | .. |3_Naturality| image:: ../images/2015/04/3_naturality.jpg 246 | :class: alignnone wp-image-4349 247 | :width: 216px 248 | :height: 179px 249 | :target: ../images/2015/04/3_naturality.jpg 250 | .. |Sheets| image:: ../images/2015/11/sheets.png 251 | :class: alignnone size-full wp-image-5221 252 | :target: ../images/2015/11/sheets.png 253 | -------------------------------------------------------------------------------- /src/part3/19-free-forgetful-adjunctions.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Free/Forgetful Adjunctions 3 | ========================== 4 | 5 | Free constructions are a powerful application of adjunctions. A *free 6 | functor* is defined as the left adjoint to a *forgetful functor*. A 7 | forgetful functor is usually a pretty simple functor that forgets some 8 | structure. For instance, lots of interesting categories are built on top 9 | of sets. But categorical objects, which abstract those sets, have no 10 | internal structure — they have no elements. Still, those objects often 11 | carry the memory of sets, in the sense that there is a mapping — a 12 | functor — from a given category *C* to **Set**. A set corresponding to 13 | some object in *C* is called its *underlying set*. 14 | 15 | Monoids are such objects that have underlying sets — sets of elements. 16 | There is a forgetful functor ``U`` from the category of monoids **Mon** 17 | to the category of sets, which maps monoids to their underlying sets. It 18 | also maps monoid morphisms (homomorphisms) to functions between sets. 19 | 20 | I like to think of **Mon** as having split personality. On the one hand, 21 | it’s a bunch of sets with multiplication and unit elements. On the other 22 | hand, it’s a category with featureless objects whose only structure is 23 | encoded in morphisms that go between them. Every set-function that 24 | preserves multiplication and unit gives rise to a morphism in **Mon**. 25 | 26 | Things to keep in mind: 27 | 28 | - There may be many monoids that map to the same set, and 29 | - There are fewer (or at most as many as) monoid morphisms than there 30 | are functions between their underlying sets. 31 | 32 | .. raw:: html 33 | 34 |
36 | 37 | |Forgetful| 38 | Monoids m\ :sub:`1` and m\ :sub:`2` have the same underlying set. There 39 | are more functions between the underlying sets of m\ :sub:`2` and 40 | m\ :sub:`3` than there are morphisms between them. 41 | 42 | .. raw:: html 43 | 44 |
45 | 46 | The functor ``F`` that’s the left adjoint to the forgetful functor ``U`` 47 | is the free functor that builds free monoids from their generator sets. 48 | The adjunction follows from the :doc:`free monoid universal 49 | construction <../part2/13-free-monoids>` 50 | we’ve discussed before. 51 | 52 | In terms of hom-sets, we can write this adjunction as: 53 | 54 | :: 55 | 56 | Mon(F x, m) ≅ Set(x, U m) 57 | 58 | This (natural in ``x`` and ``m``) isomorphism tells us that: 59 | 60 | - For every monoid homomorphism between the free monoid ``F x`` 61 | generated by ``x`` and an arbitrary monoid ``m`` there is a unique 62 | function that embeds the set of generators ``x`` in the underlying 63 | set of ``m``. It’s a function in ``Set(x, U m)``. 64 | - For every function that embeds ``x`` in the underlying set of some 65 | ``m`` there is a unique monoid morphism between the free monoid 66 | generated by ``x`` and the monoid ``m``. (This is the morphism we 67 | called ``h`` in our universal construction.) 68 | 69 | |FreeMonAdjunction| 70 | 71 | The intuition is that ``F x`` is the “maximum” monoid that can be built 72 | on the basis of ``x``. If we could look inside monoids, we would see 73 | that any morphism that belongs to ``Mon(F x, m)`` *embeds* this free 74 | monoid in some other monoid ``m``. It does it by possibly identifying 75 | some elements. In particular, it embeds the generators of ``F x`` (i.e., 76 | the elements of ``x``) in ``m``. The adjunction shows that the embedding 77 | of ``x``, which is given by a function from ``Set(x, U m)`` on the 78 | right, uniquely determines the embedding of monoids on the left, and 79 | vice versa. 80 | 81 | In Haskell, the list data structure is a free monoid (with some caveats: 82 | see `Dan Doel’s blog 83 | post `__). A 84 | list type ``[a]`` is a free monoid with the type ``a`` representing the 85 | set of generators. For instance, the type ``[Char]`` contains the unit 86 | element — the empty list ``[]`` — and the singletons like ``['a']``, 87 | ``['b']`` — the generators of the free monoid. The rest is generated by 88 | applying the “product.” Here, the product of two lists simply appends 89 | one to another. Appending is associative and unital (that is, there is a 90 | neutral element — here, the empty list). A free monoid generated by 91 | ``Char`` is nothing but the set of all strings of characters from 92 | ``Char``. It’s called ``String`` in Haskell: 93 | 94 | :: 95 | 96 | type String = [Char] 97 | 98 | (``type`` defines a type synonym — a different name for an existing 99 | type). 100 | 101 | Another interesting example is a free monoid built from just one 102 | generator. It’s the type of the list of units, ``[()]``. Its elements 103 | are ``[]``, ``[()]``, ``[(), ()]``, etc. Every such list can be 104 | described by one natural number — its length. There is no more 105 | information encoded in the list of units. Appending two such lists 106 | produces a new list whose length is the sum of the lengths of its 107 | constituents. It’s easy to see that the type ``[()]`` is isomorphic to 108 | the additive monoid of natural numbers (with zero). Here are the two 109 | functions that are the inverse of each other, witnessing this 110 | isomorphism: 111 | 112 | :: 113 | 114 | toNat :: [()] -> Int 115 | toNat = length 116 | 117 | toLst :: Int -> [()] 118 | toLst n = replicate n () 119 | 120 | For simplicity I used the type ``Int`` rather than ``Natural``, but the 121 | idea is the same. The function ``replicate`` creates a list of length 122 | ``n`` pre-filled with a given value — here, the unit. 123 | 124 | Some Intuitions 125 | =============== 126 | 127 | What follows are some hand-waving arguments. Those kind of arguments are 128 | far from rigorous, but they help in forming intuitions. 129 | 130 | To get some intuition about the free/forgetful adjunctions it helps to 131 | keep in mind that functors and functions are lossy in nature. Functors 132 | may collapse multiple objects and morphisms, functions may bunch 133 | together multiple elements of a set. Also, their image may cover only 134 | part of their codomain. 135 | 136 | An “average” hom-set in **Set** will contain a whole spectrum of 137 | functions starting with the ones that are least lossy (e.g., injections 138 | or, possibly, isomorphisms) and ending with constant functions that 139 | collapse the whole domain to a single element (if there is one). 140 | 141 | I tend to think of morphisms in an arbitrary category as being lossy 142 | too. It’s just a mental model, but it’s a useful one, especially when 143 | thinking of adjunctions — in particular those in which one of the 144 | categories is **Set**. 145 | 146 | Formally, we can only speak of morphisms that are invertible 147 | (isomorphisms) or non-invertible. It’s that latter kind that may be 148 | though of as lossy. There is also a notion of mono- and epi- morphisms 149 | that generalize the idea of injective (non-collapsing) and surjective 150 | (covering the whole codomain) functions, but it’s possible to have a 151 | morphism that is both mono and epi, and which is still non-invertible. 152 | 153 | In the Free ⊣ Forgetful adjunction, we have the more constrained 154 | category *C* on the left, and a less constrained category *D* on the 155 | right. Morphisms in *C* are “fewer” because they have to preserve some 156 | additional structure. In the case of **Mon**, they have to preserve 157 | multiplication and unit. Morphisms in *D* don’t have to preserve as much 158 | structure, so there are “more” of them. 159 | 160 | When we apply a forgetful functor ``U`` to an object ``c`` in *C*, we 161 | think of it as revealing the “internal structure” of ``c``. In fact, if 162 | *D* is **Set** we think of ``U`` as *defining* the internal structure of 163 | ``c`` — its underlying set. (In an arbitrary category, we can’t talk 164 | about the internals of an object other than through its connections to 165 | other objects, but here we are just hand-waving.) 166 | 167 | If we map two objects ``c'`` and ``c`` using ``U``, we expect that, in 168 | general, the mapping of the hom-set ``C(c', c)`` will cover only a 169 | subset of ``D(U c', U c)``. That’s because morphisms in ``C(c', c)`` 170 | have to preserve the additional structure, whereas the ones in 171 | ``D(U c', U c)`` don’t. 172 | 173 | |ForgettingMorphisms| 174 | 175 | But since an adjunction is defined as an *isomporphism* of particular 176 | hom-sets, we have to be very picky with our selection of ``c'``. In the 177 | adjunction, ``c'`` is picked not from just anywhere in *C*, but from the 178 | (presumably smaller) image of the free functor ``F``: 179 | 180 | :: 181 | 182 | C(F d, c) ≅ D(d, U c) 183 | 184 | The image of ``F`` must therefore consist of objects that have lots of 185 | morphisms going to an arbitrary ``c``. In fact, there has to be as many 186 | structure-preserving morphisms from ``F d`` to ``c`` as there are 187 | non-structure preserving morphisms from ``d`` to ``U c``. It means that 188 | the image of ``F`` must consist of essentially structure-free objects 189 | (so that there is no structure to preserve by morphisms). Such 190 | “structure-free” objects are called free objects. 191 | 192 | |FreeImage| 193 | 194 | In the monoid example, a free monoid has no structure other than what’s 195 | generated by unit and associativity laws. Other than that, all 196 | multiplications produce brand new elements. 197 | 198 | In a free monoid, 2\*3 is not 6 — it’s a new element [2, 3]. Since there 199 | is no identification of [2, 3] and 6, a morphism from this free monoid 200 | to any other monoid ``m`` is allowed to map them separately. But it’s 201 | also okay for it to map both [2, 3] and 6 (their product) to the same 202 | element of ``m``. Or to identify [2, 3] and 5 (their sum) in an additive 203 | monoid, and so on. Different identifications give you different monoids. 204 | 205 | This leads to another interesting intuition: Free monoids, instead of 206 | performing the monoidal operation, accumulate the arguments that were 207 | passed to it. Instead of multiplying 2 and 3 they remember 2 and 3 in a 208 | list. The advantage of this scheme is that we don’t have to specify what 209 | monoidal operation we will use. We can keep accumulating arguments, and 210 | only at the end apply an operator to the result. And it’s then that we 211 | can chose what operator to apply. We can add the numbers, or multiply 212 | them, or perform addition modulo 2, and so on. A free monoid separates 213 | the creation of an expression from its evaluation. We’ll see this idea 214 | again when we talk about algebras. 215 | 216 | This intuition generalizes to other, more elaborate free constructions. 217 | For instance, we can accumulate whole expression trees before evaluating 218 | them. The advantage of this approach is that we can transform such trees 219 | to make the evaluation faster or less memory consuming. This is, for 220 | instance, done in implementing matrix calculus, where eager evaluation 221 | would lead to lots of allocations of temporary arrays to store 222 | intermediate results. 223 | 224 | Challenges 225 | ========== 226 | 227 | #. Consider a free monoid built from a singleton set as its generator. 228 | Show that there is a one-to-one correspondence between morphisms from 229 | this free monoid to any monoid ``m``, and functions from the 230 | singleton set to the underlying set of ``m``. 231 | 232 | Acknowledgments 233 | =============== 234 | 235 | I’d like to thank Gershom Bazerman for checking my math and logic, and André van 236 | Meulebrouck, who has been volunteering his editing help throughout this series 237 | of posts. 238 | 239 | .. |Forgetful| image:: ../images/2016/05/forgetful.jpg 240 | :class: wp-image-5532 241 | :width: 377px 242 | :height: 234px 243 | :target: ../images/2016/05/forgetful.jpg 244 | .. |FreeMonAdjunction| image:: ../images/2016/05/freemonadjunction.jpg 245 | :class: alignnone wp-image-5534 246 | :width: 512px 247 | :height: 203px 248 | :target: ../images/2016/05/freemonadjunction.jpg 249 | .. |ForgettingMorphisms| image:: ../images/2016/05/forgettingmorphisms.jpg 250 | :class: alignnone wp-image-5536 251 | :width: 413px 252 | :height: 219px 253 | :target: ../images/2016/05/forgettingmorphisms.jpg 254 | .. |FreeImage| image:: ../images/2016/05/freeimage.jpg 255 | :class: alignnone wp-image-5537 256 | :width: 422px 257 | :height: 249px 258 | :target: ../images/2016/05/freeimage.jpg 259 | -------------------------------------------------------------------------------- /src/part3/29-topoi.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Topoi 3 | ===== 4 | 5 | I realize that we might be getting away from programming and diving into 6 | hard-core math. But you never know what the next big revolution in 7 | programming might bring and what kind of math might be necessary to 8 | understand it. There are some very interesting ideas going around, like 9 | functional reactive programming with its continuous time, the extention 10 | of Haskell’s type system with dependent types, or the exploration on 11 | homotopy type theory in programming. 12 | 13 | So far I’ve been casually identifying types with *sets* of values. This 14 | is not strictly correct, because such approach doesn’t take into account 15 | the fact that, in programming, we *compute* values, and the computation 16 | is a process that takes time and, in extreme cases, might not terminate. 17 | Divergent computations are part of every Turing-complete language. 18 | 19 | There are also foundational reasons why set theory might not be the best 20 | fit as the basis for computer science or even math itself. A good 21 | analogy is that of set theory being the assembly language that is tied 22 | to a particular architecture. If you want to run your math on different 23 | architectures, you have to use more general tools. 24 | 25 | One possibility is to use spaces in place of sets. Spaces come with more 26 | structure, and may be defined without recourse to sets. One thing 27 | usually associated with spaces is topology, which is necessary to define 28 | things like continuity. And the conventional approach to topology is, 29 | you guessed it, through set theory. In particular, the notion of a 30 | subset is central to topology. Not surprisingly, category theorists 31 | generalized this idea to categories other than **Set**. The type of 32 | category that has just the right properties to serve as a replacement 33 | for set theory is called a *topos* (plural: topoi), and it provides, 34 | among other things, a generalized notion of a subset. 35 | 36 | Subobject Classifier 37 | ==================== 38 | 39 | Let’s start by trying to express the idea of a subset using functions 40 | rather than elements. Any function ``f`` from some set ``a`` to ``b`` 41 | defines a subset of ``b``–that of the image of ``a`` under ``f``. But 42 | there are many functions that define the same subset. We need to be more 43 | specific. To begin with, we might focus on functions that are injective 44 | — ones that don’t smush multiple elements into one. Injective functions 45 | “inject” one set into another. For finite sets, you may visualize 46 | injective functions as parallel arrows connecting elements of one set to 47 | elements of another. Of course, the first set cannot be larger than the 48 | second set, or the arrows would necessarily converge. There is still 49 | some ambiguity left: there may be another set ``a'`` and another 50 | injective function ``f'`` from that set to ``b`` that picks the same 51 | subset. But you can easily convince yourself that such a set would have 52 | to be isomorphic to ``a``. We can use this fact to define a subset as a 53 | family of injective functions that are related by isomorphisms of their 54 | domains. More precisely, we say that two injective functions: 55 | 56 | .. code-block:: haskell 57 | 58 | f :: a -> b 59 | f':: a'-> b 60 | 61 | are equivalent if there is an isomorphism: 62 | 63 | .. code-block:: haskell 64 | 65 | h :: a -> a' 66 | 67 | such that: 68 | 69 | .. code-block:: haskell 70 | 71 | f = f' . h 72 | 73 | Such a family of equivalent injections defines a subset of ``b``. 74 | 75 | |image0| 76 | 77 | This definition can be lifted to an arbitrary category if we replace 78 | injective functions with monomorphism. Just to remind you, a 79 | monomorphism ``m`` from ``a`` to ``b`` is defined by its universal 80 | property. For any object ``c`` and any pair of morphisms: 81 | 82 | .. code-block:: haskell 83 | 84 | g :: c -> a 85 | g':: c -> a 86 | 87 | such that: 88 | 89 | .. code-block:: haskell 90 | 91 | m . g = m . g' 92 | 93 | it must be that ``g = g'``. 94 | 95 | |image1| 96 | 97 | On sets, this definition is easier to understand if we consider what it 98 | would mean for a function ``m`` *not* to be a monomorphism. It would map 99 | two different elements of ``a`` to a single element of ``b``. We could 100 | then find two functions ``g`` and ``g'`` that differ only at those two 101 | elements. The postcomposition with ``m`` would then mask this 102 | difference. 103 | 104 | |image2| 105 | 106 | There is another way of defining a subset: using a single function 107 | called the characteristic function. It’s a function ``χ`` from the set 108 | ``b`` to a two-element set ``Ω``. One element of this set is designated 109 | as “true” and the other as “false.” This function assigns “true” to 110 | those elements of ``b`` that are members of the subset, and “false” to 111 | those that aren’t. 112 | 113 | It remains to specify what it means to designate an element of ``Ω`` as 114 | “true.” We can use the standard trick: use a function from a singleton 115 | set to ``Ω``. We’ll call this function ``true``: 116 | 117 | .. code-block:: haskell 118 | 119 | true :: 1 -> Ω 120 | 121 | |image3| 122 | 123 | These definitions can be combined in such a way that they not only 124 | define what a subobject is, but also define the special object ``Ω`` 125 | without talking about elements. The idea is that we want the morphism 126 | ``true`` to represent a “generic” subobject. In **Set**, it picks a 127 | single-element subset from a two-element set ``Ω``. This is as generic 128 | as it gets. It’s clearly a proper subset, because ``Ω`` has one more 129 | element that’s *not* in that subset. 130 | 131 | In a more general setting, we define ``true`` to be a monomorphism from 132 | the terminal object to the *classifying object* ``Ω``. But we have to 133 | define the classifying object. We need a universal property that links 134 | this object to the characteristic function. It turns out that, in 135 | **Set**, the pullback of ``true`` along the characteristic function 136 | ``χ`` defines both the subset ``a`` and the injective function that 137 | embeds it in ``b``. Here’s the pullback diagram: 138 | 139 | |image4| 140 | 141 | Let’s analyze this diagram. The pullback equation is: 142 | 143 | .. code-block:: haskell 144 | 145 | true . unit = χ . f 146 | 147 | The function ``true . unit`` maps every element of ``a`` to “true.” 148 | Therefore ``f`` must map all elements of ``a`` to those elements of 149 | ``b`` for which ``χ`` is “true.” These are, by definition, the elements 150 | of the subset that is specified by the characteristic function ``χ``. So 151 | the image of ``f`` is indeed the subset in question. The universality of 152 | the pullback guarantees that ``f`` is injective. 153 | 154 | This pullback diagram can be used to define the classifying object in 155 | categories other than **Set**. Such a category must have a terminal 156 | object, which will let us define the monomorphism ``true``. It must also 157 | have pullbacks — the actual requirement is that it must have all finite 158 | limits (a pullback is an example of a finite limit). Under those 159 | assumptions, we define the classifying object ``Ω`` by the property 160 | that, for every monomorphism ``f`` there is a unique morphism ``χ`` that 161 | completes the pullback diagram. 162 | 163 | Let’s analyze the last statement. When we construct a pullback, we are 164 | given three objects ``Ω``, ``b`` and ``1``; and two morphisms, ``true`` 165 | and ``χ``. The existence of a pullback means that we can find the best 166 | such object ``a``, equipped with two morphisms ``f`` and ``unit`` (the 167 | latter is uniquely determined by the definition of the terminal object), 168 | that make the diagram commute. 169 | 170 | Here we are solving a different system of equations. We are solving for 171 | ``Ω`` and ``true`` while varying both ``a`` *and* ``b``. For a given 172 | ``a`` and ``b`` there may or may not be a monomorphism ``f::a->b``. But 173 | if there is one, we want it to be a pullback of some ``χ``. Moreover, we 174 | want this ``χ`` to be uniquely determined by ``f``. 175 | 176 | We can’t say that there is a one-to-one correspondence between 177 | monomorphisms ``f`` and characteristic functions ``χ``, because a 178 | pullback is only unique up to isomorphism. But remember our earlier 179 | definition of a subset as a family of equivalent injections. We can 180 | generalize it by defining a subobject of ``b`` as a family of equivalent 181 | monomorphisms to ``b``. This family of monomorphisms is in one-to-one 182 | corrpespondence with the family of equivalent pullbacks of our diagram. 183 | 184 | We can thus define a set of subobjects of ``b``, ``Sub(b)``, as a family 185 | of monomorphisms, and see that it is isomorphic to the set of morphisms 186 | from ``b`` to ``Ω``: 187 | 188 | :: 189 | 190 | Sub(b) ≅ C(b, Ω) 191 | 192 | This happens to be a natural isomorphism of two functors. In other 193 | words, ``Sub(-)`` is a representable (contravariant) functor whose 194 | representation is the object Ω. 195 | 196 | Topos 197 | ===== 198 | 199 | A topos is a category that: 200 | 201 | #. Is cartesian closed: It has all products, the terminal object, and 202 | exponentials (defined as right adjoints to products), 203 | #. Has limits for all finite diagrams, 204 | #. Has a subobject classifier ``Ω``. 205 | 206 | This set of properties makes a topos a shoe-in for **Set** in most 207 | applications. It also has additional properties that follow from its 208 | definition. For instance, a topos has all finite colimits, including the 209 | initial object. 210 | 211 | It would be tempting to define the subobject classifier as a coproduct 212 | (sum) of two copies of the terminal object –that’s what it is in 213 | **Set**— but we want to be more general than that. Topoi in which this 214 | is true are called Boolean. 215 | 216 | Topoi and Logic 217 | =============== 218 | 219 | In set theory, a characteristic function may be interpreted as defining 220 | a property of the elements of a set — a *predicate* that is true for 221 | some elements and false for others. The predicate ``isEven`` selects a 222 | subset of even numbers from the set of natural numbers. In a topos, we 223 | can generalize the idea of a predicate to be a morphism from object 224 | ``a`` to ``Ω``. This is why ``Ω`` is sometimes called the truth object. 225 | 226 | Predicates are the building blocks of logic. A topos contains all the 227 | necessary instrumentation to study logic. It has products that 228 | correspond to logical conjunctions (logical *and*), coproducts for 229 | disjunctions (logical *or*), and exponentials for implications. All 230 | standard axioms of logic hold in a topos except for the law of excluded 231 | middle (or, equivalently, double negation elimination). That’s why the 232 | logic of a topos corresponds to constructive or intuitionistic logic. 233 | 234 | Intuitionistic logic has been steadily gaining ground, finding 235 | unexpected support from computer science. The classical notion of 236 | excluded middle is based on the belief that there is absolute truth: Any 237 | statement is either true or false or, as Ancient Romans would say, 238 | *tertium non datur* (there is no third option). But the only way we can 239 | know whether something is true or false is if we can prove or disprove 240 | it. A proof is a process, a computation — and we know that computations 241 | take time and resources. In some cases, they may never terminate. It 242 | doesn’t make sense to claim that a statement is true if we cannot prove 243 | it in finite amount of time. A topos with its more nuanced truth object 244 | provides a more general framework for modeling interesting logics. 245 | 246 | Challenges 247 | ========== 248 | 249 | #. Show that the function ``f`` that is the pullback of ``true`` along 250 | the characteristic function must be injective. 251 | 252 | .. |image0| image:: ../images/2017/07/subsetinjection.jpg 253 | :class: alignnone wp-image-8934 254 | :width: 220px 255 | :height: 171px 256 | :target: ../images/2017/07/subsetinjection.jpg 257 | .. |image1| image:: ../images/2017/07/monomorphism.jpg 258 | :class: alignnone size-medium wp-image-8931 259 | :width: 300px 260 | :height: 174px 261 | :target: ../images/2017/07/monomorphism.jpg 262 | .. |image2| image:: ../images/2017/07/notmono.jpg 263 | :class: alignnone size-medium wp-image-8932 264 | :width: 300px 265 | :height: 126px 266 | :target: ../images/2017/07/notmono.jpg 267 | .. |image3| image:: ../images/2017/07/true.jpg 268 | :class: alignnone wp-image-8935 269 | :width: 190px 270 | :height: 123px 271 | :target: ../images/2017/07/true.jpg 272 | .. |image4| image:: ../images/2017/07/pullback.jpg 273 | :class: alignnone wp-image-8933 274 | :width: 232px 275 | :height: 164px 276 | :target: ../images/2017/07/pullback.jpg 277 | -------------------------------------------------------------------------------- /src/part3/31-monads-monoids-and-categories.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | Monads, Monoids, and Categories 3 | =============================== 4 | 5 | There is no good place to end a book on category theory. There’s always 6 | more to learn. Category theory is a vast subject. At the same time, it’s 7 | obvious that the same themes, concepts, and patterns keep showing up 8 | over and over again. There is a saying that all concepts are Kan 9 | extensions and, indeed, you can use Kan extensions to derive limits, 10 | colimits, adjunctions, monads, the Yoneda lemma, and much more. The 11 | notion of a category itself arises at all levels of abstraction, and so 12 | does the concept of a monoid and a monad. Which one is the most basic? 13 | As it turns out they are all interrelated, one leading to another in a 14 | never-ending cycle of abstractions. I decided that showing these 15 | interconnections might be a good way to end this book. 16 | 17 | Bicategories 18 | ============ 19 | 20 | One of the most difficult aspects of category theory is the constant 21 | switching of perspectives. Take the category of sets, for instance. We 22 | are used to defining sets in terms of elements. An empty set has no 23 | elements. A singleton set has one element. A cartesian product of two 24 | sets is a set of pairs, and so on. But when talking about the category 25 | **Set** I asked you to forget about the contents of sets and instead 26 | concentrate on morphisms (arrows) between them. You were allowed, from 27 | time to time, to peek under the covers to see what a particular 28 | universal construction in **Set** described in terms of elements. The 29 | terminal object turned out to be a set with one element, and so on. But 30 | these were just sanity checks. 31 | 32 | A functor is defined as a mapping of categories. It’s natural to 33 | consider a mapping as a morphism in a category. A functor turned out to 34 | be a morphism in the category of categories (small categories, if we 35 | want to avoid questions about size). By treating a functor as an arrow, 36 | we forfeit the information about its action on the internals of a 37 | category (its objects and morphisms), just like we forfeit the 38 | information about the action of a function on elements of a set when we 39 | treat it as an arrow in **Set**. But functors between any two categories 40 | also form a category. This time you are asked to consider something that 41 | was an arrow in one category to be an object in another. In a functor 42 | category functors are objects and natural transformations are morphisms. 43 | We have discovered that the same thing can be an arrow in one category 44 | and an object in another. The naive view of objects as nouns and arrows 45 | as verbs doesn’t hold. 46 | 47 | Instead of switching between two views, we can try to merge them into 48 | one. This is how we get the concept of a 2-category, in which objects 49 | are called 0-cells, morphisms are 1-cells, and morphisms between 50 | morphisms are 2-cells. 51 | 52 | .. raw:: html 53 | 54 |
56 | 57 | |image0| 58 | 0-cells a, b; 1-cells f, g; and a 2-cell α. 59 | 60 | .. raw:: html 61 | 62 |
63 | 64 | The category of categories **Cat** is an immediate example. We have 65 | categories as 0-cells, functors as 1-cells, and natural transformations 66 | as 2-cells. The laws of a 2-category tell us that 1-cells between any 67 | two 0-cells form a category (in other words, ``C(a, b)`` is a 68 | hom-category rather than a hom-set). This fits nicely with our earlier 69 | assertion that functors between any two categories form a functor 70 | category. 71 | 72 | In particular, 1-cells from any 0-cell back to itself also form a 73 | category, the hom-category ``C(a, a)``; but that category has even more 74 | structure. Members of ``C(a, a)`` can be viewed as arrows in **C** or as 75 | objects in ``C(a, a)``. As arrows, they can be composed with each other. 76 | But when we look at them as objects, the composition becomes a mapping 77 | from a pair of objects to an object. In fact it looks very much like a 78 | product — a tensor product to be precise. This tensor product has a 79 | unit: the identity 1-cell. It turns out that, in any 2-category, a 80 | hom-category ``C(a, a)`` is automatically a monoidal category with the 81 | tensor product defined as composition of 1-cells. Associativity and unit 82 | laws simply fall out from the corresponding category laws. 83 | 84 | Let’s see what this means in our canonical example of a 2-category 85 | **Cat**. The hom-category ``Cat(a, a)`` is the category of endofunctors 86 | on ``a``. Endofunctor composition plays the role of a tensor product in 87 | it. The identity functor is the unit with respect to this product. We’ve 88 | seen before that endofunctors form a monoidal category (we used this 89 | fact in the definition of a monad), but now we see that this is a more 90 | general phenomenon: endo-1-cells in any 2-category form a monoidal 91 | category. We’ll come back to it later when we generalize monads. 92 | 93 | You might recall that, in a general monoidal category, we did not insist 94 | on the monoid laws being satisfied on the nose. It was often enough for 95 | the unit laws and the associativity laws to be satisfied up to 96 | isomorphism. In a 2-category, monoidal laws in ``C(a, a)`` follow from 97 | composition laws for 1-cells. These laws are strict, so we will always 98 | get a strict monoidal category. It is, however, possible to relax these 99 | laws as well. We can say, for instance, that a composition of the 100 | identity 1-cell ``ida`` with another 1-cell, ``f :: a -> b``, is 101 | isomorphic, rather than equal, to ``f``. Isomorphism of 1-cells is 102 | defined using 2-cells. In other words, there is a 2-cell: 103 | 104 | :: 105 | 106 | ρ :: f ∘ ida -> f 107 | 108 | that has an inverse. 109 | 110 | .. raw:: html 111 | 112 |
114 | 115 | |image1| 116 | Identity law in a bicategory holds up to isomorphism (an invertible 117 | 2-cell ρ). 118 | 119 | .. raw:: html 120 | 121 |
122 | 123 | We can do the same for the left identity and associativity laws. This 124 | kind of relaxed 2-category is called a bicategory (there are some 125 | additional coherency laws, which I will omit here). 126 | 127 | As expected, endo-1-cells in a bicategory form a general monoidal 128 | category with non-strict laws. 129 | 130 | An interesting example of a bicategory is the category of spans. A span 131 | between two objects ``a`` and ``b`` is an object ``x`` and a pair of 132 | morphisms: 133 | 134 | :: 135 | 136 | f :: x -> a 137 | g :: x -> b 138 | 139 | | |image2| 140 | | You might recall that we used spans in the definition of a categorical 141 | product. Here, we want to look at spans as 1-cells in a bicategory. 142 | The first step is to define a composition of spans. Suppose that we 143 | have an adjoining span: 144 | 145 | :: 146 | 147 | f':: y -> b 148 | g':: y -> c 149 | 150 | | |image3| 151 | | The composition would be a third span, with some apex ``z``. The most 152 | natural choice for it is the pullback of ``g`` along ``f'``. Remember 153 | that a pullback is the object ``z`` together with two morphisms: 154 | 155 | :: 156 | 157 | h :: z -> x 158 | h':: z -> y 159 | 160 | such that: 161 | 162 | :: 163 | 164 | g ∘ h = f' ∘ h' 165 | 166 | which is universal among all such objects. 167 | 168 | | |image4| 169 | | For now, let’s concentrate on spans over the category of sets. In that 170 | case, the pullback is just a set of pairs ``(p, q)`` from the 171 | cartesian product ``x × y`` such that: 172 | 173 | :: 174 | 175 | g p = f' q 176 | 177 | A morphism between two spans that share the same endpoints is defined as 178 | a morphism ``h`` between their apices, such that the appropriate 179 | triangles commute. 180 | 181 | .. raw:: html 182 | 183 |
185 | 186 | |image5| 187 | A 2-cell in **Span**. 188 | 189 | .. raw:: html 190 | 191 |
192 | 193 | To summarize, in the bicategory **Span**: 0-cells are sets, 1-cells are 194 | spans, 2-cells are span morphisms. An identity 1-cell is a degenerate 195 | span in which all three objects are the same, and the two morphisms are 196 | identities. 197 | 198 | We’ve seen another example of a bicategory before: the bicategory 199 | **Prof** of 200 | `profunctors `__, 201 | where 0-cells are categories, 1-cells are profunctors, and 2-cells are 202 | natural transformations. The composition of profunctors was given by a 203 | coend. 204 | 205 | Monads 206 | ====== 207 | 208 | By now you should be pretty familiar with the definition of a monad as a 209 | monoid in the category of endofunctors. Let’s revisit this definition 210 | with the new understanding that the category of endofunctors is just one 211 | small hom-category of endo-1-cells in the bicategory **Cat**. We know 212 | it’s a monoidal category: the tensor product comes from the composition 213 | of endofunctors. A monoid is defined as an object in a monoidal category 214 | — here it will be an endofunctor ``T`` — together with two morphisms. 215 | Morphisms between endofunctors are natural transformations. One morphism 216 | maps the monoidal unit — the identity endofunctor — to ``T``: 217 | 218 | :: 219 | 220 | η :: I -> T 221 | 222 | The second morphism maps the tensor product of ``T ⊗ T`` to ``T``. The 223 | tensor product is given by endofunctor composition, so we get: 224 | 225 | :: 226 | 227 | μ :: T ∘ T -> T 228 | 229 | | |image6| 230 | | We recognize these as the two operations defining a monad (they are 231 | called ``return`` and ``join`` in Haskell), and we know that monoid 232 | laws turn to monad laws. 233 | 234 | Now let’s remove all mention of endofunctors from this definition. We 235 | start with a bicategory ``C`` and pick a 0-cell ``a`` in it. As we’ve 236 | seen earlier, the hom-category ``C(a, a)`` is a monoidal category. We 237 | can therefore define a monoid in ``C(a, a)`` by picking a 1-cell, ``T``, 238 | and two 2-cells: 239 | 240 | :: 241 | 242 | η :: I -> T 243 | μ :: T ∘ T -> T 244 | 245 | satisfying the monoid laws. We call *this* a monad. 246 | 247 | | |image7| 248 | | That’s a much more general definition of a monad using only 0-cells, 249 | 1-cells, and 2-cells. It reduces to the usual monad when applied to 250 | the bicategory **Cat**. But let’s see what happens in other 251 | bicategories. 252 | 253 | Let’s construct a monad in **Span**. We pick a 0-cell, which is a set 254 | that, for reasons that will become clear soon, I will call ``Ob``. Next, 255 | we pick an endo-1-cell: a span from ``Ob`` back to ``Ob``. It has a set 256 | at the apex, which I will call ``Ar``, equipped with two functions: 257 | 258 | :: 259 | 260 | dom :: Ar -> Ob 261 | cod :: Ar -> Ob 262 | 263 | | |image8| 264 | | Let’s call the elements of the set ``Ar`` “arrows.” If I also tell you 265 | to call the elements of ``Ob`` “objects,” you might get a hint where 266 | this is leading to. The two functions ``dom`` and ``cod`` assign the 267 | domain and the codomain to an “arrow.” 268 | 269 | To make our span into a monad, we need two 2-cells, ``η`` and ``μ``. The 270 | monoidal unit, in this case, is the trivial span from ``Ob`` to ``Ob`` 271 | with the apex at ``Ob`` and two identity functions. The 2-cell ``η`` is 272 | a function between the apices ``Ob`` and ``Arr``. In other words, ``η`` 273 | assigns an “arrow” to every “object.” A 2-cell in **Span** must satisfy 274 | commutation conditions — in this case: 275 | 276 | :: 277 | 278 | dom ∘ η = id 279 | cod ∘ η = id 280 | 281 | | |image9| 282 | | In components, this becomes: 283 | 284 | :: 285 | 286 | dom (η ob) = ob = cod (η ob) 287 | 288 | where ``ob`` is an “object” in ``Ob``. In other words, ``η`` assigns to 289 | every “object” and “arrow” whose domain and codomain are that “object.” 290 | We’ll call this special “arrow” the “identity arrow.” 291 | 292 | The second 2-cell ``μ`` acts on the composition of the span ``Ar`` with 293 | itself. The composition is defined as a pullback, so its elements are 294 | pairs of elements from ``Ar`` — pairs of “arrows” ``(a1, a2)``. The 295 | pullback condition is: 296 | 297 | :: 298 | 299 | cod a1 = dom a2 300 | 301 | | We say that ``a1`` and ``a1`` are “composable,” because the domain of 302 | one is the codomain of the other. 303 | | |image10| 304 | 305 | The 2-cell ``μ`` is a function that maps a pair of composable arrows 306 | ``(a1, a2)`` to a single arrow ``a3`` from ``Ar``. In other words ``μ`` 307 | defines composition of arrows. 308 | 309 | It’s easy to check that monad laws correspond to identity and 310 | associativity laws for arrows. We have just defined a category (a small 311 | category, mind you, in which objects and arrows form sets). 312 | 313 | So, all told, a category is just a monad in the bicategory of spans. 314 | 315 | What is amazing about this result is that it puts categories on the same 316 | footing as other algebraic structures like monads and monoids. There is 317 | nothing special about being a category. It’s just two sets and four 318 | functions. In fact we don’t even need a separate set for objects, 319 | because objects can be identified with identity arrows (they are in 320 | one-to-one correspondence). So it’s really just a set and a few 321 | functions. Considering the pivotal role that category theory plays in 322 | all of mathematics, this is a very humbling realization. 323 | 324 | Challenges 325 | ========== 326 | 327 | #. Derive unit and associativity laws for the tensor product defined as 328 | composition of endo-1-cells in a bicategory. 329 | #. Check that monad laws for a monad in **Span** correspond to identity 330 | and associativity laws in the resulting category. 331 | #. Show that a monad in **Prof** is an identity-on-objects functor. 332 | #. What’s a monad algebra for a monad in **Span**? 333 | 334 | Bibliography 335 | ============ 336 | 337 | #. `Paweł Sobociński’s 338 | blog. `__ 339 | 340 | .. |image0| image:: ../images/2017/09/twocat.png 341 | :class: wp-image-9117 342 | :width: 147px 343 | :height: 130px 344 | :target: ../images/2017/09/twocat.png 345 | .. |image1| image:: ../images/2017/09/bicat.png 346 | :class: wp-image-9107 347 | :width: 164px 348 | :height: 116px 349 | :target: ../images/2017/09/bicat.png 350 | .. |image2| image:: ../images/2017/09/span.png 351 | :class: alignnone wp-image-9113 352 | :width: 141px 353 | :height: 91px 354 | :target: ../images/2017/09/span.png 355 | .. |image3| image:: ../images/2017/09/compspan.png 356 | :class: alignnone wp-image-9109 357 | :width: 217px 358 | :height: 88px 359 | :target: ../images/2017/09/compspan.png 360 | .. |image4| image:: ../images/2017/09/pullspan.png 361 | :class: alignnone wp-image-9112 362 | :width: 233px 363 | :height: 146px 364 | :target: ../images/2017/09/pullspan.png 365 | .. |image5| image:: ../images/2017/09/morphspan.png 366 | :class: wp-image-9111 367 | :width: 164px 368 | :height: 144px 369 | :target: ../images/2017/09/morphspan.png 370 | .. |image6| image:: ../images/2017/09/monad.png 371 | :class: alignnone wp-image-9110 372 | :width: 130px 373 | :height: 124px 374 | :target: ../images/2017/09/monad.png 375 | .. |image7| image:: ../images/2017/09/bimonad.png 376 | :class: alignnone wp-image-9108 377 | :width: 134px 378 | :height: 179px 379 | :target: ../images/2017/09/bimonad.png 380 | .. |image8| image:: ../images/2017/09/spanmonad.png 381 | :class: alignnone wp-image-9114 382 | :width: 184px 383 | :height: 143px 384 | :target: ../images/2017/09/spanmonad.png 385 | .. |image9| image:: ../images/2017/09/spanunit.png 386 | :class: alignnone wp-image-9116 387 | :width: 218px 388 | :height: 148px 389 | :target: ../images/2017/09/spanunit.png 390 | .. |image10| image:: ../images/2017/09/spanmul.png 391 | :class: alignnone wp-image-9115 392 | :width: 264px 393 | :height: 158px 394 | :target: ../images/2017/09/spanmul.png 395 | -------------------------------------------------------------------------------- /src/preface.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Preface 3 | ======= 4 | 5 | For some time now I’ve been floating the idea of writing a book about category 6 | theory that would be targeted at programmers. Mind you, not computer scientists 7 | but programmers — engineers rather than scientists. I know this sounds crazy and 8 | I am properly scared. I can’t deny that there is a huge gap between science and 9 | engineering because I have worked on both sides of the divide. But I’ve always 10 | felt a very strong compulsion to explain things. I have tremendous admiration 11 | for Richard Feynman who was the master of simple explanations. I know I’m no 12 | Feynman, but I will try my best. I’m starting by publishing this preface — which 13 | is supposed to motivate the reader to learn category theory — in hopes of 14 | starting a discussion and soliciting feedback. 15 | 16 | I will attempt, in the space of a few paragraphs, to convince you that 17 | this book is written for you, and whatever objections you might have to 18 | learning one of the most abstract branches of mathematics in your 19 | “copious spare time” are totally unfounded. 20 | 21 | My optimism is based on several observations. First, category theory is 22 | a treasure trove of extremely useful programming ideas. Haskell 23 | programmers have been tapping this resource for a long time, and the 24 | ideas are slowly percolating into other languages, but this process is 25 | too slow. We need to speed it up. 26 | 27 | Second, there are many different kinds of math, and they appeal to 28 | different audiences. You might be allergic to calculus or algebra, but 29 | it doesn’t mean you won’t enjoy category theory. I would go as far as 30 | to argue that category theory is the kind of math that is particularly 31 | well suited for the minds of programmers. That’s because category theory 32 | — rather than dealing with particulars — deals with structure. It deals 33 | with the kind of structure that makes programs composable. 34 | 35 | Composition is at the very root of category theory — it’s part of the 36 | definition of the category itself. And I will argue strongly that 37 | composition is the essence of programming. We’ve been composing things 38 | forever, long before some great engineer came up with the idea of a 39 | subroutine. Some time ago the principles of structural programming 40 | revolutionized programming because they made blocks of code composable. 41 | Then came object oriented programming, which is all about composing 42 | objects. Functional programming is not only about composing functions 43 | and algebraic data structures — it makes concurrency composable — 44 | something that’s virtually impossible with other programming paradigms. 45 | 46 | Third, I have a secret weapon, a butcher’s knife, with which I will 47 | butcher math to make it more palatable to programmers. When you’re a 48 | professional mathematician, you have to be very careful to get all your 49 | assumptions straight, qualify every statement properly, and construct 50 | all your proofs rigorously. This makes mathematical papers and books 51 | extremely hard to read for an outsider. I’m a physicist by training, and 52 | in physics we made amazing advances using informal reasoning. 53 | Mathematicians laughed at the Dirac delta function, which was made up on 54 | the spot by the great physicist P. A. M. Dirac to solve some 55 | differential equations. They stopped laughing when they discovered a 56 | completely new branch of calculus called distribution theory that 57 | formalized Dirac’s insights. 58 | 59 | Of course when using hand-waving arguments you run the risk of saying 60 | something blatantly wrong, so I will try to make sure that there is 61 | solid mathematical theory behind informal arguments in this book. I do 62 | have a worn-out copy of Saunders Mac Lane’s *Category Theory for the 63 | Working Mathematician* on my nightstand. 64 | 65 | Since this is category theory *for programmers* I will illustrate all 66 | major concepts using computer code. You are probably aware that 67 | functional languages are closer to math than the more popular imperative 68 | languages. They also offer more abstracting power. So a natural 69 | temptation would be to say: You must learn Haskell before the bounty of 70 | category theory becomes available to you. But that would imply that 71 | category theory has no application outside of functional programming and 72 | that’s simply not true. So I will provide a lot of C++ examples. 73 | Granted, you’ll have to overcome some ugly syntax, the patterns might 74 | not stand out from the background of verbosity, and you might be forced 75 | to do some copy and paste in lieu of higher abstraction, but that’s just 76 | the lot of a C++ programmer. 77 | 78 | But you’re not off the hook as far as Haskell is concerned. You don’t 79 | have to become a Haskell programmer, but you need it as a language for 80 | sketching and documenting ideas to be implemented in C++. That’s exactly 81 | how I got started with Haskell. I found its terse syntax and powerful 82 | type system a great help in understanding and implementing C++ 83 | templates, data structures, and algorithms. But since I can’t expect the 84 | readers to already know Haskell, I will introduce it slowly and explain 85 | everything as I go. 86 | 87 | If you’re an experienced programmer, you might be asking yourself: I’ve 88 | been coding for so long without worrying about category theory or 89 | functional methods, so what’s changed? Surely you can’t help but notice 90 | that there’s been a steady stream of new functional features invading 91 | imperative languages. Even Java, the bastion of object-oriented 92 | programming, let the lambdas in C++ has recently been evolving at a 93 | frantic pace — a new standard every few years — trying to catch up with 94 | the changing world. All this activity is in preparation for a disruptive 95 | change or, as we physicist call it, a phase transition. If you keep 96 | heating water, it will eventually start boiling. We are now in the 97 | position of a frog that must decide if it should continue swimming in 98 | increasingly hot water, or start looking for some alternatives. 99 | 100 | |IMG_1299| 101 | 102 | One of the forces that are driving the big change is the multicore 103 | revolution. The prevailing programming paradigm, object oriented 104 | programming, doesn’t buy you anything in the realm of concurrency and 105 | parallelism, and instead encourages dangerous and buggy design. Data 106 | hiding, the basic premise of object orientation, when combined with 107 | sharing and mutation, becomes a recipe for data races. The idea of 108 | combining a mutex with the data it protects is nice but, unfortunately, 109 | locks don’t compose, and lock hiding makes deadlocks more likely and 110 | harder to debug. 111 | 112 | But even in the absence of concurrency, the growing complexity of 113 | software systems is testing the limits of scalability of the imperative 114 | paradigm. To put it simply, side effects are getting out of hand. 115 | Granted, functions that have side effects are often convenient and easy 116 | to write. Their effects can in principle be encoded in their names and 117 | in the comments. A function called SetPassword or WriteFile is obviously 118 | mutating some state and generating side effects, and we are used to 119 | dealing with that. It’s only when we start composing functions that have 120 | side effects on top of other functions that have side effects, and so 121 | on, that things start getting hairy. It’s not that side effects are 122 | inherently bad — it’s the fact that they are hidden from view that makes 123 | them impossible to manage at larger scales. Side effects don’t scale, 124 | and imperative programming is all about side effects. 125 | 126 | Changes in hardware and the growing complexity of software are forcing 127 | us to rethink the foundations of programming. Just like the builders of 128 | Europe’s great gothic cathedrals we’ve been honing our craft to the 129 | limits of material and structure. There is an unfinished gothic 130 | `cathedral in 131 | Beauvais `__, France, 132 | that stands witness to this deeply human struggle with limitations. It 133 | was intended to beat all previous records of height and lightness, but 134 | it suffered a series of collapses. Ad hoc measures like iron rods and 135 | wooden supports keep it from disintegrating, but obviously a lot of 136 | things went wrong. From a modern perspective, it’s a miracle that so 137 | many gothic structures had been successfully completed without the help 138 | of modern material science, computer modelling, finite element analysis, 139 | and general math and physics. I hope future generations will be as 140 | admiring of the programming skills we’ve been displaying in building 141 | complex operating systems, web servers, and the internet infrastructure. 142 | And, frankly, they should, because we’ve done all this based on very 143 | flimsy theoretical foundations. We have to fix those foundations if we 144 | want to move forward. 145 | 146 | .. |IMG_1299| image:: images/2014/10/img_1299.jpg 147 | :class: aligncenter wp-image-3468 size-medium 148 | :width: 300px 149 | :height: 213px 150 | :target: images/2014/10/img_1299.jpg 151 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | Eventually we need to copy all of the images from the blog locally. This way the 4 | reader won't need internet access to see them. We'll need some tooling to do that. 5 | 6 | ## get_images.py 7 | 8 | This scans an RST input file, identifies any image directives, and downloads the 9 | images. 10 | 11 | ## update_links.py (not written) 12 | 13 | This updates the RST files with new links. Perhaps this is best done with a sed 14 | script or something instead of a Python file. 15 | -------------------------------------------------------------------------------- /tools/get_images.py: -------------------------------------------------------------------------------- 1 | """Fetch all images in an RST file. 2 | 3 | In practice you'll use it something like this: 4 | 5 | for F in *rst; do python get_images.py $F; done 6 | 7 | This uses wget's recursive download support to build a directory structure 8 | containing all of the downloaded files. 9 | """ 10 | 11 | import subprocess 12 | import sys 13 | 14 | 15 | def clean_uri(uri): 16 | "Remove query parameters from a URI." 17 | return uri.split('?')[0] 18 | 19 | 20 | def uris(filename): 21 | "Sequence of image URIs in an RST file." 22 | with open(filename, 'rt') as f: 23 | for line in f: 24 | if 'image::' in line: 25 | uri = line.split('image::')[-1] 26 | yield clean_uri(uri) 27 | 28 | 29 | def main(filename): 30 | "Use wget to fetch all images from an RST file." 31 | for uri in uris(filename): 32 | subprocess.run('wget -m {}'.format(uri).split()) 33 | 34 | 35 | if __name__ == '__main__': 36 | main(sys.argv[1]) 37 | --------------------------------------------------------------------------------