refactor: CI and nix (#306)

* fix: remove custom fonts

Since they are available in Nix, there is no need to keep them in the project anymore

* chore: remove old obsolete files

* refactor: rewrite Nix files

- Switch from `numtide/flake-utils` to `flake-parts`
- Add custom font derivation for LaTeX
- Add `formatter`
- Switch to `python311`

* ci: update Github workflows

* feat: add `Makefile` for local development

Very useful when used in combination with `nix develop`

* feat: add `.envrc` file for loading development environment with `nix-direnv`

* feat: add `.editorconfig` and `.prettierrc`

* style: reformat files using `prettier`

Run `nix run nixpkgs#nodePackages.prettier -- --write .`

* fix: add workaround to prevent bug with `minted` package

see https://github.com/gpoore/minted/issues/353 for context

* fix: add `version.tex` in the repo

* chore: rewrite `README`

* chore: ignore LaTeX temporary files while building locally

* feat: add `latexindent.pl` configuration file

* style: lint LaTeX files
This commit is contained in:
Pol Dellaiera 2023-02-02 10:53:45 +01:00 committed by GitHub
parent 98b71ac267
commit de799935b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
124 changed files with 2408 additions and 2272 deletions

21
.editorconfig Normal file
View File

@ -0,0 +1,21 @@
root = true
[*]
indent_size = 4
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[Makefile]
indent_style = tab
[*.{tex,cls,lua,nix}]
indent_style = space
indent_size = 2
max_line_length = 80
[*.md]
trim_trailing_whitespace = false
indent_size = 2
max_line_length = 80

2
.envrc Normal file
View File

@ -0,0 +1,2 @@
use flake .
use flake github:loophp/nix-prettier

51
.github/settings.yml vendored Normal file
View File

@ -0,0 +1,51 @@
# https://github.com/probot/settings
branches:
- name: master
protection:
enforce_admins: false
required_pull_request_reviews:
dismiss_stale_reviews: true
require_code_owner_reviews: true
required_approving_review_count: 1
restrictions: null
required_linear_history: true
required_status_checks:
strict: true
labels:
- name: typo
color: ee0701
- name: dependencies
color: 0366d6
- name: enhancement
color: 0e8a16
- name: question
color: cc317c
- name: security
color: ee0701
- name: stale
color: eeeeee
repository:
allow_merge_commit: true
allow_rebase_merge: true
allow_squash_merge: true
default_branch: master
description:
"Bartosz Milewski's 'Category Theory for Programmers' unofficial PDF and
LaTeX sources"
homepage: https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/
topics: pdf,haskell,scala,latex,cpp,functional-programming,ocaml,category-theory
has_downloads: true
has_issues: true
has_pages: false
has_projects: false
has_wiki: false
name: milewski-ctfp-pdf
private: false

View File

@ -1,117 +0,0 @@
name: Build PDFs
on:
- push
jobs:
dependencies:
name: Build dependencies
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Set up Git repository
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Create global variables
id: version
run: echo "::set-output name=version::$(git rev-parse --short HEAD)"
determine-matrix:
name: Figure out the packages we need to build
runs-on: ubuntu-latest
needs: [dependencies]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set up Git repository
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Install the Nix package manager
uses: cachix/install-nix-action@v16
- id: set-matrix
run: |
echo "::set-output name=matrix::$(
nix eval --json --impure \
--expr 'builtins.attrNames (import ./.).packages.x86_64-linux'
)"
build:
name: Build documents
needs: determine-matrix
runs-on: ubuntu-latest
strategy:
matrix:
packages: ${{fromJson(needs.determine-matrix.outputs.matrix)}}
steps:
- name: Set up Git repository
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Install Nix
uses: cachix/install-nix-action@v16
- name: Build ${{ matrix.packages }}.pdf
run: |
nix build .#${{ matrix.packages }}
mkdir -p out
cp -ar ./result/* out/
- name: Upload build assets (${{ matrix.packages }}.pdf)
uses: actions/upload-artifact@v2
with:
name: ctfp
path: out/*
release:
name: "Create Github tag/pre-release"
runs-on: ubuntu-latest
needs: [dependencies, build]
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Github pre-release (${{ needs.dependencies.outputs.version }})
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ github.run_number }}-${{ needs.dependencies.outputs.version }}
release_name: Version ${{ github.run_number }} (${{ needs.dependencies.outputs.version }})
draft: false
prerelease: true
assets:
name: Upload release assets
runs-on: ubuntu-latest
needs: [determine-matrix, dependencies, release]
strategy:
matrix:
packages: ${{fromJson(needs.determine-matrix.outputs.matrix)}}
steps:
- name: Download build assets (${{ matrix.packages }}.pdf)
uses: actions/download-artifact@v2
with:
name: ctfp
path: ctfp
- name: Upload release assets (${{ matrix.packages }}--${{ needs.dependencies.outputs.version }}.pdf)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release.outputs.upload_url }}
asset_path: ctfp/${{ matrix.packages }}.pdf
asset_name: ${{ matrix.packages }}--${{ needs.dependencies.outputs.version }}.pdf
asset_content_type: application/pdf

64
.github/workflows/nix-flake-check.yaml vendored Normal file
View File

@ -0,0 +1,64 @@
name: Check and build
on:
pull_request:
push:
branches:
- master
jobs:
dependencies:
name: Build dependencies
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Set up Git repository
uses: actions/checkout@v3
- name: Create global variables
id: version
run:
echo "version=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
determine-matrix:
name: Figure out the packages we need to build
runs-on: ubuntu-latest
needs: [dependencies]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set up Git repository
uses: actions/checkout@v3
- name: Install the Nix package manager
uses: cachix/install-nix-action@v18
- id: set-matrix
run: |
echo "matrix=$(
nix eval --json .#packages.x86_64-linux --apply builtins.attrNames
)" >> $GITHUB_OUTPUT
build:
name: Build
needs: determine-matrix
runs-on: ubuntu-latest
strategy:
matrix:
packages: ${{fromJson(needs.determine-matrix.outputs.matrix)}}
steps:
- name: Set up Git repository
uses: actions/checkout@v3
- name: Install Nix
uses: cachix/install-nix-action@v18
- name: Nix flake check
run: nix flake check
- name: Build ${{ matrix.packages }}.pdf
run: nix build .#${{ matrix.packages }}

17
.github/workflows/nix-fmt-checks.yaml vendored Normal file
View File

@ -0,0 +1,17 @@
name: Nix formatter checks
on:
pull_request:
jobs:
format-check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Nix
uses: cachix/install-nix-action@v18
- name: Run nix formatter tool
run: nix fmt . -- --check

18
.github/workflows/prettier-checks.yaml vendored Normal file
View File

@ -0,0 +1,18 @@
name: Prettier checks
on:
pull_request:
jobs:
prettier:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install the Nix package manager
uses: cachix/install-nix-action@v18
- name: Checks
run: nix run nixpkgs#nodePackages.prettier -- --check .

99
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,99 @@
name: Release PDFs
on:
push:
tags:
- "**"
jobs:
determine-matrix:
name: Figure out the assets we need to build
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set up Git repository
uses: actions/checkout@v3
- name: Install the Nix package manager
uses: cachix/install-nix-action@v18
- id: set-matrix
run: |
echo "matrix=$(
nix eval --json --impure \
--expr 'builtins.filter (x: (null == builtins.match "(.*)-nts" x)) (builtins.attrNames (import ./.).packages.x86_64-linux)'
)" >> $GITHUB_OUTPUT
build:
name: Build documents
needs: determine-matrix
runs-on: ubuntu-latest
strategy:
matrix:
packages: ${{fromJson(needs.determine-matrix.outputs.matrix)}}
steps:
- name: Set up Git repository
uses: actions/checkout@v3
- name: Install Nix
uses: cachix/install-nix-action@v18
- name: Build ${{ matrix.packages }}.pdf
run: |
nix build .#${{ matrix.packages }}
mkdir -p out
cp -ar ./result/* out/
- name: Upload build assets (${{ matrix.packages }}.pdf)
uses: actions/upload-artifact@v2
with:
name: ctfp
path: out/*
release:
name: "Create Github pre-release"
runs-on: ubuntu-latest
needs: [build]
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Github pre-release (${{ github.ref }})
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: true
assets:
name: Upload release assets
runs-on: ubuntu-latest
needs: [determine-matrix, release]
strategy:
matrix:
packages: ${{fromJson(needs.determine-matrix.outputs.matrix)}}
steps:
- name: Download build assets (${{ matrix.packages }}.pdf)
uses: actions/download-artifact@v2
with:
name: ctfp
path: ctfp
- name:
Upload release assets (${{ matrix.packages }}--${{ github.ref
}}.pdf)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release.outputs.upload_url }}
asset_path: ctfp/${{ matrix.packages }}.pdf
asset_name: ${{ matrix.packages }}--${{ github.ref }}.pdf
asset_content_type: application/pdf

28
.gitignore vendored
View File

@ -1,16 +1,26 @@
.vscode/
*.fls
/.vscode/
/.direnv/
/build/
/result
.DS_Store
src/.dotty-ide-disabled
src/.metals
out/
_minted*
*.fdb_latexmk
*.fls
out/*
*.fdb_latexmk
*.bak*
*.log
*.pdf
*.xdv
*.gz
src/version.tex
*.pyg
*.synctex(busy)
src/.dotty-ide-disabled
venv/*
.DS_Store
src/.metals
out/
*.aux
*.idx
*.ilg
*.lig
*.ind
*.out
*.toc

7
.latexindent.yaml Normal file
View File

@ -0,0 +1,7 @@
defaultIndent: " "
verbatimEnvironments:
verbatim: 1
lstlisting: 1
minted: 1
snip: 1
snipv: 1

6
.prettierignore Normal file
View File

@ -0,0 +1,6 @@
/.direnv/
/.idea/
/vendor/
/docs/
/build/
CHANGELOG.md

3
.prettierrc Normal file
View File

@ -0,0 +1,3 @@
{
"proseWrap": "always"
}

View File

@ -1,32 +0,0 @@
language:
- nix
script:
- nix-shell --pure --command 'cd src; make all'
cache:
directories:
src/_minted-ctfp
deploy:
- provider: releases
api_key:
secure: usNWQZc/HcrZxR72+Qz2YXeyf56h0EwLVl6oOXIivxTWQCTTQ0cE6tXG6lP8JxQ1qlfAhbdh4QOmz6jxQD60HxsUwDWmt9t51o+8n3EMeID0hc45ES40/mbieUfR1jbkLbwmL16Z/bWsvUErmGuUgOxYrUCplK9fWs7Vvt8xmReFdunw8XpVrywG4rl1jXDo9YWihMps5KLOqd3mY3yvlxAmB+UKkhHPNdcEuEghEBhC8HZoZkFiwfRw/8PeOh9VpnQ2ht9eDXOlB7zNYY9Xr/S98FbzfZXxFjApXVRgNP8k2UYyHn8HCmIoCSs+Jv06tEvNCuwTvj0JNsuoW7vu/Q7wrrpScfDL+WnSw2CScml+xAe7Q4caoZKkzaMCnj5fHbPEZ731+SLZNbG6TMTYhMqhFm0Fr87bwdNlayqAssIhOwU4ca3pnZOQFO4vNOWblNfbHsX5F9sJDOR0uD4Y+PgfNWgTsssXqei7owBJNTe+qz5Q7IaFA3A8EMp57CV1dUCgmjxVuugtz6DLpl16WGiWpqakIA900GXMG+2c4ENCCDWmYtGlpWs2lSBqRYHV1gncE8UGtIih8G6g5jQd2aJUQKHKuaEiv/28WLI7f2exUuOBmc0ce4xP+qZAs5XWiPo4jJLNyb81uNIZ0jCb/c5+lEH8EsYF+jFOrmw17GQ=
file: out/**/*.pdf
file_glob: true
skip_cleanup: true
on:
repo: hmemcpy/milewski-ctfp-pdf
branch: master
tags: true
- provider: s3
bucket: milewski-ctfp-pdf
access_key_id: '$ARTIFACTS_KEY'
secret_access_key: '$ARTIFACTS_SECRET'
region: us-east-1
acl: public_read
local_dir: out
skip_cleanup: true
on:
all_branches: true
repo: hmemcpy/milewski-ctfp-pdf

31
Makefile Normal file
View File

@ -0,0 +1,31 @@
OUTPUT ?= $(shell basename "$(shell dirname "$(INPUT)")")
OUTPUT_DIRECTORY = $(shell pwd)/build
LATEXMK_ARGS ?= -f -file-line-error -shell-escape -logfilewarninglist -interaction=nonstopmode -halt-on-error -norc -pdflatex="xelatex %O %S" -pdfxe
TEXINPUTS = ""
TEXLIVE_RUN = TEXINPUTS=$(TEXINPUTS)
LATEXMK_COMMAND = $(TEXLIVE_RUN) latexmk $(LATEXMK_ARGS)
# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
ctfp:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp ctfp-reader.tex
ctfp-ocaml:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp-ocaml ctfp-reader-ocaml.tex
ctfp-scala:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp-scala ctfp-reader-scala.tex
ctfp-print:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp-print ctfp-print.tex
ctfp-print-ocaml:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp-print-ocaml ctfp-print-ocaml.tex
ctfp-print-scala:
cd src; $(LATEXMK_COMMAND) -jobname=ctfp-print-scala ctfp-print-scala.tex
lint:
$(foreach file, $(call rwildcard,$(shell dirname "$(INPUT)"),*.tex), latexindent -l -w $(file);)

140
README.md
View File

@ -1,76 +1,106 @@
Category Theory for Programmers
====
![image](https://user-images.githubusercontent.com/601206/43392303-f770d7be-93fb-11e8-8db8-b7e915b435ba.png)
<b>Direct link: [category-theory-for-programmers.pdf](https://github.com/hmemcpy/milewski-ctfp-pdf/releases/download/v1.3.0/category-theory-for-programmers.pdf)</b>
(Latest release: v1.3.0, August 2019. See [releases](https://github.com/hmemcpy/milewski-ctfp-pdf/releases) for additional formats and languages.)
![GitHub stars][github stars]
[![GitHub Workflow Status][github workflow status]][github actions link]
[![Download][download badge]][github latest release]
[![License][license badge]][github latest release]
[![Build Status](https://travis-ci.org/hmemcpy/milewski-ctfp-pdf.svg?branch=master)](https://travis-ci.org/hmemcpy/milewski-ctfp-pdf)
[(latest CI build)](https://s3.amazonaws.com/milewski-ctfp-pdf/category-theory-for-programmers.pdf)
# Category Theory For Programmers
<img src="https://user-images.githubusercontent.com/601206/47271389-8eea0900-d581-11e8-8e81-5b932e336336.png"
alt="Buy Category Theory for Programmers" width=410 />
**[Available in full-color hardcover print](https://www.blurb.com/b/9621951-category-theory-for-programmers-new-edition-hardco)**
Publish date: 12 August, 2019. Based off release tag [v1.3.0](https://github.com/hmemcpy/milewski-ctfp-pdf/releases/tag/v1.3.0). See [errata-1.3.0](errata-1.3.0.md) for changes and fixes since print.
An _unofficial_ PDF version of "**C**ategory **T**heory **F**or **P**rogrammers"
by [Bartosz Milewski][bartosz github], converted from his [blogpost
series][blogpost series] (_with permission!_).
**[Scala Edition is now available in paperback](https://www.blurb.com/b/9603882-category-theory-for-programmers-scala-edition-pape)**
Publish date: 12 August, 2019. Based off release tag [v1.3.0](https://github.com/hmemcpy/milewski-ctfp-pdf/releases/tag/v1.3.0). See [errata-scala](errata-scala.md) for changes and fixes since print.
![Category Theory for Programmers][ctfp image]
This is an *unofficial* PDF version of "Category Theory for Programmers" by Bartosz Milewski, converted from his [blogpost series](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/) (with permission!)
## Buy the book
---
- **[Standard edition in full-color hardcover
print][buy regular edition on blurb]**
- Publish date: 12 August, 2019.
- Based off release tag [v1.3.0][v1.3.0 github release link]. See
[errata-1.3.0](errata-1.3.0.md) for changes and fixes since print.
- **[Scala Edition in paperback][buy scala edition on blurb]**
- Publish date: 12 August, 2019.
- Based off release tag [v1.3.0][v1.3.0 github release link]. See
[errata-scala](errata-scala.md) for changes and fixes since print.
Building
--------
## Build the book
The best way to build the book is using the [Nix](https://nixos.org/nix/) package manager. After [installing Nix](https://nixos.org/download.html), if you're using a non-NixOS operating system, you need to install `nixFlakes` in your environment following the steps below ([source](https://nixos.wiki/wiki/Flakes#Non-NixOS)):
The building workflow requires [Nix][nix website]. After [installing
Nix][nix download website], you need to enable the upcoming "flake" feature
which must be [enabled manually][nixos wiki flake] the time being. This is
needed to expose the new Nix commands and flakes support that are hidden behind
feature-flags.
```bash
$ nix-env -iA nixpkgs.nixFlakes
```
Afterwards, type `nix flake show` in the root directory of the project to see
all the available versions of this book. Then type `nix build .#<edition>` to
build the edition you want (Haskell, Scala, OCaml, Reason and their printed
versions). For example, to build the Scala edition you'll have to type
`nix build .#ctfp-scala`.
Edit either `~/.config/nix/nix.conf` or `/etc/nix/nix.conf` and add:
Upon successful compilation, the PDF file will be placed in the `result`
directory.
```
experimental-features = nix-command flakes
```
The command `nix develop` will provide a shell containing all the required
dependencies to build the book manually using the provided `Makefile`. To build
the `ctfp-scala` edition, just run `make ctfp-scala`.
This is needed to expose the Nix 2.0 CLI and flakes support that are hidden behind feature-flags.
## Contribute
Also, if the Nix installation is in multi-user mode, dont forget to restart the nix-daemon.
Contributors are welcome to contribute to this book by sending pull-requests.
Once reviewed, the changes are merged in the main branch and will be
incorporated in the next release.
Afterwards, type `nix flake show` in the root directory of the project to see all the available versions of this book. Then type `nix build .#<edition>` to build the edition you want (Haskell, Scala, OCaml, Reason and their printed versions). For example, to build the Scala edition you'll have to type `nix build .#ctfp-scala`.
**Note from [Bartosz][bartosz github]**: I really appreciate all your
contributions. You made this book much better than I could have imagined. Thank
you!
Upon successful compilation, the PDF file will be placed in the `result` directory inside the root directory `milewski-ctfp-pdf` of the repository.
Find the [list of contributors on Github][contributors].
The file `preamble.tex` contains all the configuration and style declarations.
## Acknowledgements
Acknowledgements
----------------
PDF LaTeX source and the tools to create it are based on the work by [Andres
Raba][andres raba github]. The book content is taken, with permission, from
[Bartosz Milewski][bartosz github]'s blogpost series, and adapted to the LaTeX
format.
PDF LaTeX source and the tools to create it are based on the work by Andres Raba et al., available here: https://github.com/sarabander/sicp-pdf.
The book content is taken, with permission, from Bartosz Milewski's blogpost series, and adapted to the LaTeX format.
The original blog post acknowledgments by Bartosz are consolidated in the
_Acknowledgments_ page at the end of the book.
Thanks to the following people for contributing corrections/conversions and misc:
## License
* Oleg Rakitskiy
* Jared Weakly
* Paolo G. Giarrusso
* Adi Shavit
* Mico Loretan
* Marcello Seri
* Erwin Maruli Tua Pakpahan
* Markus Hauck
* Yevheniy Zelenskyy
* Ross Kirsling
* ...and many others!
The PDF book, `.tex` files, and associated images and figures in directories
`src/fig` and `src/content` are licensed under [Creative Commons
Attribution-ShareAlike 4.0 International License][license cc by sa].
The original blog post acknowledgments by Bartosz are consolidated in the *Acknowledgments* page at the end of the book.
The script files `scraper.py` and others are licensed under [GNU General Public
License version 3][license gnu gpl].
**Note from Bartosz**: I really appreciate all your contributions. You made this book much better than I could have imagined. Thank you!
License
-------
The PDF book, `.tex` files, and associated images and figures in directories `src/fig` and `src/content` are licensed under Creative Commons Attribution-ShareAlike 4.0 International License ([cc by-sa](http://creativecommons.org/licenses/by-sa/4.0/)).
The script files `scraper.py` and others are licensed under GNU General Public License version 3 (for details, see [LICENSE](https://github.com/hmemcpy/milewski-ctfp-pdf/blob/master/LICENSE)).
[download badge]:
https://img.shields.io/badge/Download-latest-green.svg?style=flat-square
[github actions link]: https://github.com/hmemcpy/milewski-ctfp-pdf/actions
[github stars]:
https://img.shields.io/github/stars/hmemcpy/milewski-ctfp-pdf.svg?style=flat-square
[github workflow status]:
https://img.shields.io/github/actions/workflow/status/hmemcpy/milewski-ctfp-pdf/build.yml?branch=master&style=flat-square
[github latest release]:
https://github.com/hmemcpy/milewski-ctfp-pdf/releases/latest
[license badge]:
https://img.shields.io/badge/License-CC_By_SA-green.svg?style=flat-square
[ctfp image]:
https://user-images.githubusercontent.com/601206/47271389-8eea0900-d581-11e8-8e81-5b932e336336.png
[bartosz github]: https://github.com/BartoszMilewski
[nixos wiki flake]: https://nixos.wiki/wiki/Flakes
[andres raba github]: https://github.com/sarabander
[contributors]: https://github.com/hmemcpy/milewski-ctfp-pdf/graphs/contributors
[license cc by sa]: https://spdx.org/licenses/CC-BY-SA-4.0.html
[license gnu gpl]: https://spdx.org/licenses/GPL-3.0.html
[blogpost series]:
https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/
[buy regular edition on blurb]:
https://www.blurb.com/b/9621951-category-theory-for-programmers-new-edition-hardco
[buy scala edition on blurb]:
https://www.blurb.com/b/9603882-category-theory-for-programmers-scala-edition-pape
[v1.3.0 github release link]:
https://github.com/hmemcpy/milewski-ctfp-pdf/releases/tag/v1.3.0
[nix website]: https://nixos.org/nix/
[nix download website]: https://nixos.org/download.html

View File

@ -1,6 +0,0 @@
let
rev = "cecfd08d13ddef8a79f277e67b8084bd9afa1586";
url = "https://github.com/edolstra/flake-compat/archive/${rev}.tar.gz";
flake = import (fetchTarball url) { src = ./.; };
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
in if inNixShell then flake.shellNix else flake.defaultNix

View File

@ -2,82 +2,111 @@
### Preface
* [#155](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/155) - Typo (physicist -> physicists)
- [#155](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/155) - Typo
(physicist -> physicists)
### 6. Simple Algebraic Data Types
* [#176](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/176) - Typo (statements -> statement)
- [#176](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/176) - Typo
(statements -> statement)
### 8. Functoriality
* [9a3a5a3](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/9a3a5a386e98ef8f926bccd08f572cc19b1a6367) - added clarifications on bifunctoriality vs. separate functoriality (fix by Bartosz)
- [9a3a5a3](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/9a3a5a386e98ef8f926bccd08f572cc19b1a6367) -
added clarifications on bifunctoriality vs. separate functoriality (fix by
Bartosz)
### 9. Function Types
* [#182](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/182) - Fix typo (chose -> choose)
- [#182](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/182) - Fix typo
(chose -> choose)
### 10. Natural Transformations
* [#157](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/157) - Adding paragraph indent
- [#157](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/157) - Adding
paragraph indent
### 12. Limits and Colimits
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 14. Representable Functors
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 18. Adjunctions
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling of "counit"
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling
of "counit"
### 19. Free/Forgetful Adjunctions
* [#156](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/156) - an instance of the category name **Mon** is appearing as **arg**
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling of "isomorphism"
- [#156](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/156) - an instance of
the category name **Mon** is appearing as **arg**
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling
of "isomorphism"
### 20. Monads - Programmer's Definition
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix grammatical error
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix
grammatical error
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 22. Monads Categorically
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 23. Comonads
* [#158](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/158) - fixed incorrect typesetting of `set`
* [23f522e](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/23f522ec083c2c98f28f15935ff2893ccd1fa76c) - adjusted `Prod`/`Product` names (fix by Bartosz)
- [#158](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/158) - fixed
incorrect typesetting of `set`
- [23f522e](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/23f522ec083c2c98f28f15935ff2893ccd1fa76c) -
adjusted `Prod`/`Product` names (fix by Bartosz)
### 25. Algebras for Monads
* [#158](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/158) - fixed incorrect typesetting of `set`
* [#159](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/159) - fixed incorrect typesetting of category terms
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling of "counit" and "morphisms", fix subscript spacing
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical errors
- [#158](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/158) - fixed
incorrect typesetting of `set`
- [#159](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/159) - fixed
incorrect typesetting of category terms
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling
of "counit" and "morphisms", fix subscript spacing
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical errors
### 26. Ends and Coends
* [#159](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/159) - fixed incorrect typesetting of category terms
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling of "coequalizer", fix subscript spacing
- [#159](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/159) - fixed
incorrect typesetting of category terms
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling
of "coequalizer", fix subscript spacing
### 27. Kan Extensions
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix subscript spacing
* [31821e5](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/31821e5ded0dacf059e1fcb985be406e8a495107) - postcomposition -> precomposition (fix by Bartosz)
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix subscript
spacing
- [31821e5](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/31821e5ded0dacf059e1fcb985be406e8a495107) -
postcomposition -> precomposition (fix by Bartosz)
### 28. Enriched Categories
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix subscript spacing
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix subscript
spacing
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 29. Topoi
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical error
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical error
### 30. Lawvere Theories
* [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling of "coequalizer"
* [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix grammatical errors and a typesetting error
- [#160](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/160) - Fix spelling
of "coequalizer"
- [#162](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/162) - Fix
grammatical errors and a typesetting error

View File

@ -1,17 +1,27 @@
## A list of typos/mistakes that were fixed after the release of the new edition (1.3.0) (12 August, 2019).
(see errata for the original edition until 1.3.0 [here](https://github.com/hmemcpy/milewski-ctfp-pdf/blob/master/errata-1.0.0.md))
(see errata for the original edition until 1.3.0
[here](https://github.com/hmemcpy/milewski-ctfp-pdf/blob/master/errata-1.0.0.md))
### Preface
* [#278](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/278) - Fixed reference to Saunders Mac Lane's *Categories for the Working Mathematician*. Was previously misreferenced as "*Category Theory* for the Working Mathematician."
- [#278](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/278) - Fixed
reference to Saunders Mac Lane's _Categories for the Working Mathematician_.
Was previously misreferenced as "_Category Theory_ for the Working
Mathematician."
### 12. Limits and Colimits
* [#278](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/278) - Fixed formatting of quotation marks around "selecting." Were previously pointing the wrong direction.
- [#278](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/278) - Fixed
formatting of quotation marks around "selecting." Were previously pointing the
wrong direction.
### 18. Adjunctions
* [#228](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/228) - Typo (adjuncion -> adjunction)
- [#228](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/228) - Typo
(adjuncion -> adjunction)
### 30. Lawvere Theories
* [#226](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/226) - fix type in diagram of monads as coends
- [#226](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/226) - fix type in
diagram of monads as coends

View File

@ -2,8 +2,12 @@
### 7. Functors
* [3d29cd9](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/3d29cd99f34ce1205ed9a68aeae038d9d47c7145) - Added `LazyList` example, supported since Scala 2.13
- [3d29cd9](https://github.com/hmemcpy/milewski-ctfp-pdf/commit/3d29cd99f34ce1205ed9a68aeae038d9d47c7145) -
Added `LazyList` example, supported since Scala 2.13
* [#210](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/210) - Section 6.4 - `prodToSum` snippet. Explicitly Tupling return type to avoid adapted args warning, which is deprecated behavior
- [#210](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/210) - Section 6.4 -
`prodToSum` snippet. Explicitly Tupling return type to avoid adapted args
warning, which is deprecated behavior
* [#243](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/243) - Section 8.7 - Change bimap to dimap in Profunctor definition
- [#243](https://github.com/hmemcpy/milewski-ctfp-pdf/pull/243) - Section 8.7 -
Change bimap to dimap in Profunctor definition

View File

@ -1,40 +1,60 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1674771137,
"narHash": "sha256-Zpk1GbEsYrqKmuIZkx+f+8pU0qcCYJoSUwNz1Zk+R00=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "7c7a8bce3dffe71203dcd4276504d1cb49dfe05f",
"type": "github"
},
"original": {
"id": "flake-parts",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1645379616,
"narHash": "sha256-eLzR3MRS9hcNqSWZxP6BP7xiBjgC3/pB5n2Q0lLFe/g=",
"lastModified": 1675153841,
"narHash": "sha256-EWvU3DLq+4dbJiukfhS7r6sWZyJikgXn6kNl7eHljW8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "40ef692a55b188b1f5ae3967f3fc7808838c3f1d",
"rev": "ea692c2ad1afd6384e171eabef4f0887d2b882d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-21.11",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1672350804,
"narHash": "sha256-jo6zkiCabUBn3ObuKXHGqqORUMH27gYDIFFfLq5P4wg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "677ed08a50931e38382dbef01cba08a8f7eac8f6",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}
},

340
flake.nix
View File

@ -1,149 +1,203 @@
{
description = "Category Theory for Programmers";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
inputs.utils.url = "github:numtide/flake-utils";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system: let
inherit (nixpkgs) lib;
pkgs = nixpkgs.legacyPackages.${system};
###########################################################################
# LaTeX Environment
texliveEnv = pkgs.texlive.combine {
inherit (pkgs.texlive)
bookcover
textpos
fgruler
tcolorbox
fvextra
framed
newtx
nowidow
emptypage
wrapfig
subfigure
adjustbox
collectbox
tikz-cd
imakeidx
idxlayout
titlesec
subfiles
lettrine
upquote
libertine
mweights
fontaxes
mdframed
needspace
xifthen
ifnextok
currfile
noindentafter
ifmtarg
scheme-medium
listings
minted
microtype
babel
todonotes
chngcntr
ifplatform
xstring
minifp
titlecaps
enumitem
environ
trimspaces
l3packages
zref
catchfile
import
;
};
###########################################################################
# Python Environment
# Pin the Python version and its associated package set in a single place.
python = pkgs.python38;
pythonPkgs = pkgs.python38Packages;
pygments-style-github = pythonPkgs.buildPythonPackage rec {
pname = "pygments-style-github";
version = "0.4";
doCheck = false; # Hopefully someone else has run the tests.
src = pythonPkgs.fetchPypi {
inherit pname version;
sha256 = "19zl8l5fyb8z3j8pdlm0zbgag669af66f8gn81ichm3x2hivvjhg";
};
# Anything depending on this derivation is probably also gonna want
# pygments to be available.
propagatedBuildInputs = with pythonPkgs; [ pygments ];
};
pythonEnv = python.withPackages (p: [ p.pygments pygments-style-github ]);
commonAttrs = {
nativeBuildInputs = [ texliveEnv pythonEnv pkgs.which ];
FONTCONFIG_FILE = pkgs.makeFontsConf {
fontDirectories = with pkgs; [ inconsolata-lgc libertine libertinus ];
};
};
mkLatex = variant: edition: let
maybeVariant = lib.optionalString (variant != null) "-${variant}";
maybeEdition = lib.optionalString (edition != null) "-${edition}";
variantStr = if variant == null then "reader" else variant;
suffix = maybeVariant + maybeEdition;
basename = "ctfp-${variantStr}${maybeEdition}";
version = self.shortRev or self.lastModifiedDate;
in pkgs.stdenv.mkDerivation (commonAttrs // {
inherit basename version;
name = "ctfp${suffix}-${version}";
fullname = "ctfp${suffix}";
src = "${self}/src";
configurePhase = ''
echo -n "\\newcommand{\\OPTversion}{$version}" > version.tex
'';
buildPhase = ''
latexmk -shell-escape -interaction=nonstopmode -halt-on-error \
-norc -jobname=ctfp -pdflatex="xelatex %O %S" -pdf "$basename.tex"
'';
installPhase = "install -m 0644 -vD ctfp.pdf \"$out/$fullname.pdf\"";
passthru.packageName = "ctfp${suffix}";
});
editions = [ null "scala" "ocaml" "reason" ];
variants = [ null "print" ];
in {
# nix build .#ctfp
# nix build .#ctfp-print
# nix build .#ctfp-print-ocaml
# etc etc
packages = lib.listToAttrs (lib.concatMap (variant: map (edition: rec {
name = value.packageName;
value = mkLatex variant edition;
}) editions) variants);
# nix build .
defaultPackage = self.packages.${system}.ctfp;
# nix develop .
devShell = pkgs.mkShell (commonAttrs // {
nativeBuildInputs = commonAttrs.nativeBuildInputs ++ [
pkgs.git pkgs.gnumake
outputs = inputs @ {
self,
flake-parts,
nixpkgs,
}:
flake-parts.lib.mkFlake {inherit inputs;} {
systems = [
"x86_64-linux"
"x86_64-darwin"
"aarch64-linux"
"aarch64-darwin"
];
});
});
perSystem = {
config,
pkgs,
system,
...
}: let
inherit (nixpkgs) lib;
pkgs = nixpkgs.legacyPackages.${system};
###########################################################################
# LaTeX font
inconsolata-lgc-latex = pkgs.stdenvNoCC.mkDerivation {
name = "inconsolata-lgc-latex";
pname = "inconsolata-lgc-latex";
src = pkgs.inconsolata-lgc;
dontConfigure = true;
sourceRoot = ".";
installPhase = ''
runHook preInstall
find $src -name '*.ttf' -exec install -m644 -Dt $out/fonts/truetype/public/inconsolata-lgc/ {} \;
find $src -name '*.otf' -exec install -m644 -Dt $out/fonts/opentype/public/inconsolata-lgc/ {} \;
runHook postInstall
'';
tlType = "run";
};
###########################################################################
# LaTeX Environment
texliveEnv = pkgs.texlive.combine {
inherit
(pkgs.texlive)
adjustbox
alegreya
babel
bookcover
catchfile
chngcntr
collectbox
currfile
emptypage
enumitem
environ
fgruler
fontaxes
framed
fvextra
idxlayout
ifmtarg
ifnextok
ifplatform
imakeidx
import
inconsolata
l3packages
lettrine
libertine
libertinus-fonts
listings
mdframed
microtype
minifp
minted
mweights
needspace
newtx
noindentafter
nowidow
scheme-medium
subfigure
subfiles
textpos
tcolorbox
tikz-cd
titlecaps
titlesec
todonotes
trimspaces
upquote
wrapfig
xifthen
xpatch
xstring
zref
;
inconsolata-lgc-latex = {
pkgs = [inconsolata-lgc-latex];
};
};
###########################################################################
# Python Environment
# Pin the Python version and its associated package set in a single place.
python = pkgs.python311;
pythonPkgs = pkgs.python311Packages;
pygments-style-github = pythonPkgs.buildPythonPackage rec {
pname = "pygments-style-github";
version = "0.4";
doCheck = false; # Hopefully someone else has run the tests.
src = pythonPkgs.fetchPypi {
inherit pname version;
sha256 = "19zl8l5fyb8z3j8pdlm0zbgag669af66f8gn81ichm3x2hivvjhg";
};
# Anything depending on this derivation is probably also gonna want
# pygments to be available.
propagatedBuildInputs = with pythonPkgs; [pygments];
};
pythonEnv = python.withPackages (p: [p.pygments pygments-style-github]);
commonAttrs = {
nativeBuildInputs = [texliveEnv pythonEnv pkgs.which];
};
mkLatex = variant: edition: let
maybeVariant = lib.optionalString (variant != null) "-${variant}";
maybeEdition = lib.optionalString (edition != null) "-${edition}";
variantStr =
if variant == null
then "reader"
else variant;
suffix = maybeVariant + maybeEdition;
basename = "ctfp-${variantStr}${maybeEdition}";
version = self.shortRev or self.lastModifiedDate;
in
pkgs.stdenv.mkDerivation (commonAttrs
// {
inherit basename version;
name = "ctfp${suffix}";
fullname = "ctfp${suffix}";
src = "${self}/src";
configurePhase = ''
substituteInPlace "version.tex" --replace "dev" "${version}"
'';
buildPhase = ''
latexmk -file-line-error -shell-escape -logfilewarninglist -interaction=nonstopmode -halt-on-error \
-norc -jobname=ctfp -pdflatex="xelatex %O %S" -pdfxe "$basename.tex"
'';
installPhase = "install -m 0644 -vD ctfp.pdf \"$out/$fullname.pdf\"";
passthru.packageName = "ctfp${suffix}";
});
editions = [null "scala" "ocaml" "reason"];
variants = [null "print"];
in rec {
formatter = pkgs.alejandra;
packages = lib.listToAttrs (lib.concatMap (variant:
map (edition: rec {
name = value.packageName;
value = mkLatex variant edition;
})
editions)
variants);
# nix develop .
devShells.default = pkgs.mkShellNoCC (commonAttrs
// {
nativeBuildInputs =
commonAttrs.nativeBuildInputs
++ [
pkgs.git
pkgs.gnumake
];
});
};
};
}

View File

@ -1,12 +0,0 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{
src = ./.;
}
).shellNix

17
src/.gitignore vendored
View File

@ -1,17 +0,0 @@
*.aux
*.cp*
*.fn
*.ky
*.log
*.pg
*.toc
*.tp
*.vr
*.vim
*.idx
*.ilg
*.ind
*.out
*.swp
*~
ctfp.fdb_latexmk

View File

@ -1,85 +0,0 @@
# Igal Tabachnik, 2007.
# Based on work by Andres Raba et al., 2013-2015.
.PHONY: default all clean out-dir version.tex scala ocaml reason
DIR := $(shell pwd)
GIT_VER := $(shell git describe --tags --always --long | tr -d '\n')
OUTPUT_DIR := ../out
OUTPUT = category-theory-for-programmers
# Default top-level LaTeX to generate
DEFAULTTOPTEX = ctfp-reader.tex ctfp-print.tex
SCALATEXFILES = ctfp-reader-scala.tex ctfp-print-scala.tex # todo make this a macro
OCAMLTEXFILES = ctfp-reader-ocaml.tex ctfp-print-ocaml.tex # todo make this a macro
REASONTEXFILES = ctfp-reader-reason.tex ctfp-print-reason.tex # todo make this a macro
# Top-level LaTeX files from which CTFP book can be generated
TOPTEXFILES = version.tex $(DEFAULTTOPTEX) $(SCALATEXFILES) $(OCAMLTEXFILES) $(REASONTEXFILES)
# Default PDF file to make
DEFAULTPDF:=$(DEFAULTTOPTEX:.tex=.pdf)
# Scala PDF file to make
SCALAPDF:=$(SCALATEXFILES:.tex=.pdf)
# OCaml PDF file to make
OCAMLPDF:=$(OCAMLTEXFILES:.tex=.pdf)
# ReasonML PDF file to make
REASONPDF:=$(REASONTEXFILES:.tex=.pdf)
# Other PDF files for the CTFP book
TOPPDFFILES:=$(TOPTEXFILES:.tex=.pdf)
# Configuration files
OPTFILES = opt-print-ustrade.tex \
opt-reader-10in.tex \
opt-scala.tex
# All the LaTeX files for the CTFP book in order of dependency
TEXFILES = $(TOPTEXFILES) $(SCALATEXFILES) $(OCAMLTEXFILES) $(REASONTEXFILES) $(OPTFILES)
default: suffix=''
default: out-dir $(DEFAULTPDF) # todo cover
all: clean default scala ocaml reason
scala: suffix='-scala'
scala: clean out-dir version.tex $(SCALAPDF)
ocaml: suffix='-ocaml'
ocaml: clean out-dir version.tex $(OCAMLPDF)
reason: suffix='-reason'
reason: clean out-dir version.tex $(REASONPDF)
# Main targets
$(TOPPDFFILES) : %.pdf : %.tex $(TEXFILES)
if which latexmk > /dev/null 2>&1 ;\
then \
latexmk -shell-escape -interaction=nonstopmode -halt-on-error -norc -jobname=ctfp -pdflatex="xelatex %O %S" -pdf $< ;\
mv ctfp.pdf $(OUTPUT_DIR)/$(subst ctfp,$(OUTPUT),$(subst ctfp-reader,$(OUTPUT),$*)).pdf ;\
else @printf "Error: unable to find latexmk. Is it installed?\n" ;\
fi
version.tex:
@printf '\\newcommand{\\OPTversion}{' > version.tex
@printf $(GIT_VER) >> version.tex
@printf '}' >> version.tex
out-dir:
@printf 'Creating output directory: $(OUTPUT_DIR)\n'
mkdir -p $(OUTPUT_DIR)
clean:
rm -f *~ *.aux {ctfp-*}.{out,log,pdf,dvi,fls,fdb_latexmk,aux,brf,bbl,idx,ilg,ind,toc,sed}
if which latexmk > /dev/null 2>&1 ; then latexmk -CA; fi
rm -rf ../out
clean-minted:
rm -rf _minted-*

View File

@ -1,11 +1,11 @@
\newcommand{\cat}{%
\symbf%
\symbf%
}
\newcommand{\idarrow}[1][]{%
\mathbf{id}_{#1}%
\mathbf{id}_{#1}%
}
\newcommand{\Lim}[1][]{%
\mathbf{Lim}{#1}%
\mathbf{Lim}{#1}%
}
\newcommand{\Set}{\cat{Set}}
\newcommand{\Rel}{\cat{Rel}}

View File

@ -10,6 +10,6 @@ typeface is Alegreya, designed by Juan Pablo del Peral.
Original book layout design and typography are done by Andres Raba. Syntax highlighting is using ``GitHub'' style for Pygments by
\urlref{https://github.com/hugomaiavieira/pygments-style-github}{Hugo Maia Vieira}.
\ifdefined\OPTCustomLanguage{%
\input{content/\OPTCustomLanguage/colophon}
}
\input{content/\OPTCustomLanguage/colophon}
}
\fi

View File

@ -1,20 +1,20 @@
% !TEX root = ../../ctfp-print.tex
\begin{quote}
For some time now I've been floating the idea of writing a book about
category theory that would be targeted at programmers. Mind you, not
computer scientists but programmers --- engineers rather than
scientists. I know this sounds crazy and I am properly scared. I can't
deny that there is a huge gap between science and engineering because I
have worked on both sides of the divide. But I've always felt a very
strong compulsion to explain things. I have tremendous admiration for
Richard Feynman who was the master of simple explanations. I know I'm no
Feynman, but I will try my best. I'm starting by publishing this preface
--- which is supposed to motivate the reader to learn category theory
--- in hopes of starting a discussion and soliciting feedback.\footnote{
You may also watch me teach this material to a live audience, at
\href{https://goo.gl/GT2UWU}{https://goo.gl/GT2UWU} (or search
``bartosz milewski category theory'' on YouTube.)}
For some time now I've been floating the idea of writing a book about
category theory that would be targeted at programmers. Mind you, not
computer scientists but programmers --- engineers rather than
scientists. I know this sounds crazy and I am properly scared. I can't
deny that there is a huge gap between science and engineering because I
have worked on both sides of the divide. But I've always felt a very
strong compulsion to explain things. I have tremendous admiration for
Richard Feynman who was the master of simple explanations. I know I'm no
Feynman, but I will try my best. I'm starting by publishing this preface
--- which is supposed to motivate the reader to learn category theory
--- in hopes of starting a discussion and soliciting feedback.\footnote{
You may also watch me teach this material to a live audience, at
\href{https://goo.gl/GT2UWU}{https://goo.gl/GT2UWU} (or search
``bartosz milewski category theory'' on YouTube.)}
\end{quote}
\lettrine[lhang=0.17]{I}{will attempt}, in the space of a few paragraphs,
@ -64,7 +64,7 @@ Of course when using hand-waving arguments you run the risk of saying
something blatantly wrong, so I will try to make sure that there is
solid mathematical theory behind informal arguments in this book. I do
have a worn-out copy of Saunders Mac Lane's \emph{Categories for
the Working Mathematician} on my nightstand.
the Working Mathematician} on my nightstand.
Since this is category theory \emph{for programmers} I will illustrate
all major concepts using computer code. You are probably aware that
@ -102,8 +102,8 @@ the position of a frog that must decide if it should continue swimming
in increasingly hot water, or start looking for some alternatives.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/img_1299.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/img_1299.jpg}
\end{figure}
\noindent
@ -136,7 +136,7 @@ us to rethink the foundations of programming. Just like the builders of
Europe's great gothic cathedrals we've been honing our craft to the
limits of material and structure. There is an unfinished gothic
\urlref{http://en.wikipedia.org/wiki/Beauvais_Cathedral}{cathedral in
Beauvais}, France, that stands witness to this deeply human struggle
Beauvais}, France, that stands witness to this deeply human struggle
with limitations. It was intended to beat all previous records of height
and lightness, but it suffered a series of collapses. Ad hoc measures
like iron rods and wooden supports keep it from disintegrating, but
@ -151,7 +151,7 @@ all this based on very flimsy theoretical foundations. We have to fix
those foundations if we want to move forward.
\begin{figure}
\centering
\includegraphics[totalheight=0.5\textheight]{images/beauvais_interior_supports.jpg}
\caption{Ad hoc measures preventing the Beauvais cathedral from collapsing.}
\centering
\includegraphics[totalheight=0.5\textheight]{images/beauvais_interior_supports.jpg}
\caption{Ad hoc measures preventing the Beauvais cathedral from collapsing.}
\end{figure}

View File

@ -12,11 +12,11 @@ object $B$ to object $C$, then there must be an arrow --- their composition
--- that goes from $A$ to $C$.
\begin{figure}
\centering
\includegraphics[width=0.8\textwidth]{images/img_1330.jpg}
\caption{In a category, if there is an arrow going from $A$ to $B$ and an arrow going from $B$ to $C$
then there must also be a direct arrow from $A$ to $C$ that is their composition. This diagram is not a full
category because its missing identity morphisms (see later).}
\centering
\includegraphics[width=0.8\textwidth]{images/img_1330.jpg}
\caption{In a category, if there is an arrow going from $A$ to $B$ and an arrow going from $B$ to $C$
then there must also be a direct arrow from $A$ to $C$ that is their composition. This diagram is not a full
category because its missing identity morphisms (see later).}
\end{figure}
\section{Arrows as Functions}
@ -100,30 +100,30 @@ There are two extremely important properties that the composition in any
category must satisfy.
\begin{enumerate}
\item
Composition is associative. If you have three morphisms, $f$, $g$, and $h$,
that can be composed (that is, their objects match end-to-end), you
don't need parentheses to compose them. In math notation this is
expressed as:
\[h \circ (g \circ f) = (h \circ g) \circ f = h \circ g \circ f\]
In (pseudo) Haskell:
\item
Composition is associative. If you have three morphisms, $f$, $g$, and $h$,
that can be composed (that is, their objects match end-to-end), you
don't need parentheses to compose them. In math notation this is
expressed as:
\[h \circ (g \circ f) = (h \circ g) \circ f = h \circ g \circ f\]
In (pseudo) Haskell:
\src{snippet04}[b]
(I said ``pseudo,'' because equality is not defined for functions.)
\src{snippet04}[b]
(I said ``pseudo,'' because equality is not defined for functions.)
Associativity is pretty obvious when dealing with functions, but it may
be not as obvious in other categories.
Associativity is pretty obvious when dealing with functions, but it may
be not as obvious in other categories.
\item
For every object $A$ there is an arrow which is a unit of composition.
This arrow loops from the object to itself. Being a unit of composition
means that, when composed with any arrow that either starts at $A$ or ends
at $A$, respectively, it gives back the same arrow. The unit arrow for
object A is called $\idarrow[A]$ (\newterm{identity} on $A$). In math
notation, if $f$ goes from $A$ to $B$ then
\[f \circ \idarrow[A] = f\]
and
\[\idarrow[B] \circ f = f\]
\item
For every object $A$ there is an arrow which is a unit of composition.
This arrow loops from the object to itself. Being a unit of composition
means that, when composed with any arrow that either starts at $A$ or ends
at $A$, respectively, it gives back the same arrow. The unit arrow for
object A is called $\idarrow[A]$ (\newterm{identity} on $A$). In math
notation, if $f$ goes from $A$ to $B$ then
\[f \circ \idarrow[A] = f\]
and
\[\idarrow[B] \circ f = f\]
\end{enumerate}
When dealing with functions, the identity arrow is implemented as the
identity function that just returns back its argument. The
@ -209,7 +209,7 @@ imposed on us by computers. It reflects the limitations of the human
mind. Our brains can only deal with a small number of concepts at a
time. One of the most cited papers in psychology,
\urlref{http://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two}{The
Magical Number Seven, Plus or Minus Two}, postulated that we can only
Magical Number Seven, Plus or Minus Two}, postulated that we can only
keep $7 \pm 2$ ``chunks'' of information in our minds. The details of our
understanding of the human short-term memory might be changing, but we
know for sure that it's limited. The bottom line is that we are unable
@ -251,23 +251,23 @@ advantages of your programming paradigm.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Implement, as best as you can, the identity function in your favorite
language (or the second favorite, if your favorite language happens to
be Haskell).
\item
Implement the composition function in your favorite language. It takes
two functions as arguments and returns a function that is their
composition.
\item
Write a program that tries to test that your composition function
respects identity.
\item
Is the world-wide web a category in any sense? Are links morphisms?
\item
Is Facebook a category, with people as objects and friendships as
morphisms?
\item
When is a directed graph a category?
\tightlist
\item
Implement, as best as you can, the identity function in your favorite
language (or the second favorite, if your favorite language happens to
be Haskell).
\item
Implement the composition function in your favorite language. It takes
two functions as arguments and returns a function that is their
composition.
\item
Write a program that tries to test that your composition function
respects identity.
\item
Is the world-wide web a category in any sense? Are links morphisms?
\item
Is Facebook a category, with people as objects and friendships as
morphisms?
\item
When is a directed graph a category?
\end{enumerate}

View File

@ -10,7 +10,7 @@ category inside another. The source category serves as a model, a
blueprint, for some structure that's part of the target category.
\begin{figure}[H]
\centering\includegraphics[width=0.4\textwidth]{images/1_functors.jpg}
\centering\includegraphics[width=0.4\textwidth]{images/1_functors.jpg}
\end{figure}
\noindent
@ -29,8 +29,8 @@ A mapping of functors should therefore map $F a$ to
$G a$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/2_natcomp.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/2_natcomp.jpg}
\end{figure}
\noindent
@ -64,26 +64,26 @@ and $b$ in $\cat{C}$. It's mapped to two morphisms, $F\ f$
and $G f$ in $\cat{D}$:
\begin{gather*}
F f \Colon F a \to F b \\
G f \Colon G a \to G b
F f \Colon F a \to F b \\
G f \Colon G a \to G b
\end{gather*}
The natural transformation $\alpha$ provides two additional morphisms
that complete the diagram in \emph{D}:
\begin{gather*}
\alpha_a \Colon F a \to G a \\
\alpha_b \Colon F b \to G b
\alpha_a \Colon F a \to G a \\
\alpha_b \Colon F b \to G b
\end{gather*}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/3_naturality.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/3_naturality.jpg}
\end{figure}
\noindent
Now we have two ways of getting from $F a$ to $G b$. To
make sure that they are equal, we must impose the \newterm{naturality
condition} that holds for any $f$:
condition} that holds for any $f$:
\[G f \circ \alpha_a = \alpha_b \circ F f\]
The naturality condition is a pretty stringent requirement. For
@ -94,8 +94,8 @@ $\alpha_a$ along $f$:
\[\alpha_b = (G f) \circ \alpha_a \circ (F f)^{-1}\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/4_transport.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/4_transport.jpg}
\end{figure}
\noindent
@ -114,8 +114,8 @@ also say that it maps morphisms to commuting squares --- there is one
commuting naturality square in $\cat{D}$ for every morphism in $\cat{C}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/naturality.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/naturality.jpg}
\end{figure}
\noindent
@ -215,9 +215,9 @@ limitations on the implementation --- one formula for all types. These
limitations translate into equational theorems about such functions. In
the case of functions that transform functors, free theorems are the
naturality conditions.\footnote{
You may read more about free theorems in my
blog \href{https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/}{``Parametricity:
Money for Nothing and Theorems for Free}.''}
You may read more about free theorems in my
blog \href{https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/}{``Parametricity:
Money for Nothing and Theorems for Free}.''}
One way of thinking about functors in Haskell that I mentioned earlier
is to consider them generalized containers. We can continue this analogy
@ -405,8 +405,8 @@ $\beta \cdot \alpha$ --- the composition of two natural transformations $\beta$
\[(\beta \cdot \alpha)_a = \beta_a \circ \alpha_a\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/5_vertical.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/5_vertical.jpg}
\end{figure}
\noindent
@ -415,8 +415,8 @@ composition is indeed a natural transformation from F to H:
\[H f \circ (\beta \cdot \alpha)_a = (\beta \cdot \alpha)_b \circ F f\]
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/6_verticalnaturality.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/6_verticalnaturality.jpg}
\end{figure}
\noindent
@ -438,8 +438,8 @@ composition is important in defining the functor category. I'll explain
horizontal composition shortly.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/6a_vertical.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/6a_vertical.jpg}
\end{figure}
\noindent
@ -458,8 +458,8 @@ functors. A Hom-set in $\Cat$ is a set of functors. For instance
$\cat{Cat(C, D)}$ is a set of functors between two categories $\cat{C}$ and $\cat{D}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/7_cathomset.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/7_cathomset.jpg}
\end{figure}
\noindent
@ -506,18 +506,18 @@ morphisms between morphisms.
In the case of $\Cat$ seen as a $\cat{2}$-category we have:
\begin{itemize}
\tightlist
\item
Objects: (Small) categories
\item
1-morphisms: Functors between categories
\item
2-morphisms: Natural transformations between functors.
\tightlist
\item
Objects: (Small) categories
\item
1-morphisms: Functors between categories
\item
2-morphisms: Natural transformations between functors.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/8_cat-2-cat.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/8_cat-2-cat.jpg}
\end{figure}
\noindent
@ -534,21 +534,21 @@ do they interact with each other?
Let's pick two functors, or 1-morphisms, in $\Cat$:
\begin{gather*}
F \Colon \cat{C} \to \cat{D} \\
G \Colon \cat{D} \to \cat{E}
F \Colon \cat{C} \to \cat{D} \\
G \Colon \cat{D} \to \cat{E}
\end{gather*}
and their composition:
\[G \circ F \Colon \cat{C} \to \cat{E}\]
Suppose we have two natural transformations, $\alpha$ and $\beta$, that act,
respectively, on functors $F$ and $G$:
\begin{gather*}
\alpha \Colon F \to F' \\
\beta \Colon G \to G'
\alpha \Colon F \to F' \\
\beta \Colon G \to G'
\end{gather*}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/10_horizontal.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/10_horizontal.jpg}
\end{figure}
\noindent
@ -563,8 +563,8 @@ Having $\alpha$ and $\beta$ at our disposal, can we define a natural transformat
from $G \circ F$ to $G' \circ F'$? Let me sketch the construction.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/9_horizontal.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/9_horizontal.jpg}
\end{figure}
\noindent
@ -577,14 +577,14 @@ objects: $G (F a)$, $G'(F a)$, $G (F'a)$, $G'(F'a)$.
We also have four morphisms forming a square. Two of these morphisms are
the components of the natural transformation $\beta$:
\begin{gather*}
\beta_{F a} \Colon G (F a) \to G'(F a) \\
\beta_{F'a} \Colon G (F'a) \to G'(F'a)
\beta_{F a} \Colon G (F a) \to G'(F a) \\
\beta_{F'a} \Colon G (F'a) \to G'(F'a)
\end{gather*}
The other two are the images of $\alpha_a$ under the two
functors (functors map morphisms):
\begin{gather*}
G \alpha_a \Colon G (F a) \to G (F'a) \\
G'\alpha_a \Colon G'(F a) \to G'(F'a)
G \alpha_a \Colon G (F a) \to G (F'a) \\
G'\alpha_a \Colon G'(F a) \to G'(F'a)
\end{gather*}
That's a lot of morphisms. Our goal is to find a morphism that goes from
$G (F a)$ to $G'(F'a)$, a candidate for the
@ -592,8 +592,8 @@ component of a natural transformation connecting the two functors $G \circ F$
and $G' \circ F'$. In fact there's not one but two paths we can take from
$G (F a)$ to $G'(F'a)$:
\begin{gather*}
G'\alpha_a \circ \beta_{F a} \\
\beta_{F'a} \circ G \alpha_a
G'\alpha_a \circ \beta_{F a} \\
\beta_{F'a} \circ G \alpha_a
\end{gather*}
Luckily for us, they are equal, because the square we have formed turns
out to be the naturality square for $\beta$.
@ -620,8 +620,8 @@ categories, the ones that are connected by the functors it transforms.
We can think of it as connecting these two categories.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/sideways.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/sideways.jpg}
\end{figure}
\noindent
@ -689,36 +689,36 @@ natural transformation is a special type of polymorphic function.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Define a natural transformation from the \code{Maybe} functor to the
list functor. Prove the naturality condition for it.
\item
Define at least two different natural transformations between
\code{Reader ()} and the list functor. How many different lists of
\code{()} are there?
\item
Continue the previous exercise with \code{Reader Bool} and
\code{Maybe}.
\item
Show that horizontal composition of natural transformation satisfies
the naturality condition (hint: use components). It's a good exercise
in diagram chasing.
\item
Write a short essay about how you may enjoy writing down the evident
diagrams needed to prove the interchange law.
\item
Create a few test cases for the opposite naturality condition of
transformations between different \code{Op} functors. Here's one
choice:
\tightlist
\item
Define a natural transformation from the \code{Maybe} functor to the
list functor. Prove the naturality condition for it.
\item
Define at least two different natural transformations between
\code{Reader ()} and the list functor. How many different lists of
\code{()} are there?
\item
Continue the previous exercise with \code{Reader Bool} and
\code{Maybe}.
\item
Show that horizontal composition of natural transformation satisfies
the naturality condition (hint: use components). It's a good exercise
in diagram chasing.
\item
Write a short essay about how you may enjoy writing down the evident
diagrams needed to prove the interchange law.
\item
Create a few test cases for the opposite naturality condition of
transformations between different \code{Op} functors. Here's one
choice:
\begin{snip}{haskell}
\begin{snip}{haskell}
op :: Op Bool Int
op = Op (\x -> x > 0)
\end{snip}
and
and
\begin{snip}{haskell}
\begin{snip}{haskell}
f :: String -> Int
f x = read x
\end{snip}

View File

@ -12,8 +12,8 @@ happily hitting random keys, producing programs, compiling, and running
them.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/img_1329.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/img_1329.jpg}
\end{figure}
\noindent
@ -71,7 +71,7 @@ optional. Programmers tend to use them anyway, because they can tell a
lot about the semantics of code, and they make compilation errors easier
to understand. It's a common practice in Haskell to start a project by
designing the types. \sloppy{Later, type annotations drive the implementation
and become compiler-enforced comments.}
and become compiler-enforced comments.}
Strong static typing is often used as an excuse for not testing the
code. You may sometimes hear Haskell programmers saying, ``If it
@ -178,8 +178,8 @@ complications, so at this point I will use my butcher's knife and
terminate this line of reasoning. From the pragmatic point of view, it's
okay to ignore non-terminating functions and bottoms, and treat
$\Hask$ as bona fide $\Set$.\footnote{Nils Anders Danielsson,
John Hughes, Patrik Jansson, Jeremy Gibbons, \href{http://www.cs.ox.ac.uk/jeremy.gibbons/publications/fast+loose.pdf}{
Fast and Loose Reasoning is Morally Correct}. This paper provides justification for ignoring bottoms in most contexts.}
John Hughes, Patrik Jansson, Jeremy Gibbons, \href{http://www.cs.ox.ac.uk/jeremy.gibbons/publications/fast+loose.pdf}{
Fast and Loose Reasoning is Morally Correct}. This paper provides justification for ignoring bottoms in most contexts.}
\section{Why Do We Need a Mathematical Model?}
@ -292,7 +292,7 @@ cannot be easily modelled as a mathematical function.
In programming languages, functions that always produce the same result
given the same input and have no side effects are called \newterm{pure
functions}. In a pure functional language like Haskell all functions are
functions}. In a pure functional language like Haskell all functions are
pure. Because of that, it's easier to give these languages denotational
semantics and model them using category theory. As for other languages,
it's always possible to restrict yourself to a pure subset, or reason
@ -433,61 +433,61 @@ have the form \code{ctype::is(alpha, c)}, \code{ctype::is(digit, c)}, etc.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Define a higher-order function (or a function object) \code{memoize}
in your favorite language. This function takes a pure function
\code{f} as an argument and returns a function that behaves almost
exactly like \code{f}, except that it only calls the original
function once for every argument, stores the result internally, and
subsequently returns this stored result every time it's called with
the same argument. You can tell the memoized function from the
original by watching its performance. For instance, try to memoize a
function that takes a long time to evaluate. You'll have to wait for
the result the first time you call it, but on subsequent calls, with
the same argument, you should get the result immediately.
\item
Try to memoize a function from your standard library that you normally
use to produce random numbers. Does it work?
\item
Most random number generators can be initialized with a seed.
Implement a function that takes a seed, calls the random number
generator with that seed, and returns the result. Memoize that
function. Does it work?
\item
Which of these C++ functions are pure? Try to memoize them and observe
what happens when you call them multiple times: memoized and not.
\begin{enumerate}
\tightlist
\item
The factorial function from the example in the text.
Define a higher-order function (or a function object) \code{memoize}
in your favorite language. This function takes a pure function
\code{f} as an argument and returns a function that behaves almost
exactly like \code{f}, except that it only calls the original
function once for every argument, stores the result internally, and
subsequently returns this stored result every time it's called with
the same argument. You can tell the memoized function from the
original by watching its performance. For instance, try to memoize a
function that takes a long time to evaluate. You'll have to wait for
the result the first time you call it, but on subsequent calls, with
the same argument, you should get the result immediately.
\item
\begin{minted}{cpp}
Try to memoize a function from your standard library that you normally
use to produce random numbers. Does it work?
\item
Most random number generators can be initialized with a seed.
Implement a function that takes a seed, calls the random number
generator with that seed, and returns the result. Memoize that
function. Does it work?
\item
Which of these C++ functions are pure? Try to memoize them and observe
what happens when you call them multiple times: memoized and not.
\begin{enumerate}
\tightlist
\item
The factorial function from the example in the text.
\item
\begin{minted}{cpp}
std::getchar()
\end{minted}
\item
\begin{minted}{cpp}
\item
\begin{minted}{cpp}
bool f() {
std::cout << "Hello!" << std::endl;
return true;
}
\end{minted}
\item
\begin{minted}{cpp}
\item
\begin{minted}{cpp}
int f(int x) {
static int y = 0;
y += x;
return y;
}
\end{minted}
\end{enumerate}
\item
How many different functions are there from \code{Bool} to
\code{Bool}? Can you implement them all?
\item
Draw a picture of a category whose only objects are the types
\code{Void}, \code{()} (unit), and \code{Bool}; with arrows
corresponding to all possible functions between these types. Label the
arrows with the names of the functions.
\end{enumerate}
\item
How many different functions are there from \code{Bool} to
\code{Bool}? Can you implement them all?
\item
Draw a picture of a category whose only objects are the types
\code{Void}, \code{()} (unit), and \code{Bool}; with arrows
corresponding to all possible functions between these types. Label the
arrows with the names of the functions.
\end{enumerate}

View File

@ -95,7 +95,7 @@ The neutral element is zero, because:
and
\[a + 0 = a\]
The second equation is redundant, because addition is commutative $(a + b
= b + a)$, but commutativity is not part of the definition of a monoid.
= b + a)$, but commutativity is not part of the definition of a monoid.
For instance, string concatenation is not commutative and yet it forms a
monoid. The neutral element for string concatenation, by the way, is an
empty string, which can be attached to either side of a string without
@ -260,8 +260,8 @@ monoid can be described as a single object category with a set of
morphisms that follow appropriate rules of composition.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/monoid.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/monoid.jpg}
\end{figure}
\noindent
@ -289,9 +289,9 @@ this product. So we can always recover a set monoid from a category
monoid. For all intents and purposes they are one and the same.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/monoidhomset.jpg}
\caption{Monoid hom-set seen as morphisms and as points in a set.}
\centering
\includegraphics[width=0.4\textwidth]{images/monoidhomset.jpg}
\caption{Monoid hom-set seen as morphisms and as points in a set.}
\end{figure}
\noindent
@ -310,43 +310,43 @@ set $\cat{M}(m, m)$.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Generate a free category from:
\begin{enumerate}
\tightlist
\item
A graph with one node and no edges
\item
A graph with one node and one (directed) edge (hint: this edge can
be composed with itself)
\item
A graph with two nodes and a single arrow between them
\item
A graph with a single node and 26 arrows marked with the letters of
the alphabet: a, b, c \ldots{} z.
\end{enumerate}
\item
What kind of order is this?
Generate a free category from:
\begin{enumerate}
\tightlist
\begin{enumerate}
\tightlist
\item
A graph with one node and no edges
\item
A graph with one node and one (directed) edge (hint: this edge can
be composed with itself)
\item
A graph with two nodes and a single arrow between them
\item
A graph with a single node and 26 arrows marked with the letters of
the alphabet: a, b, c \ldots{} z.
\end{enumerate}
\item
A set of sets with the inclusion relation: $A$ is included in $B$ if
every element of $A$ is also an element of $B$.
What kind of order is this?
\begin{enumerate}
\tightlist
\item
A set of sets with the inclusion relation: $A$ is included in $B$ if
every element of $A$ is also an element of $B$.
\item
C++ types with the following subtyping relation: \code{T1} is a subtype of
\code{T2} if a pointer to \code{T1} can be passed to a function that expects a
pointer to \code{T2} without triggering a compilation error.
\end{enumerate}
\item
C++ types with the following subtyping relation: \code{T1} is a subtype of
\code{T2} if a pointer to \code{T1} can be passed to a function that expects a
pointer to \code{T2} without triggering a compilation error.
\end{enumerate}
\item
Considering that \code{Bool} is a set of two values \code{True} and \code{False}, show that
it forms two (set-theoretical) monoids with respect to, respectively,
operator \code{\&\&} (AND) and \code{||} (OR).
\item
Represent the \code{Bool} monoid with the AND operator as a category: List
the morphisms and their rules of composition.
\item
Represent addition modulo 3 as a monoid category.
Considering that \code{Bool} is a set of two values \code{True} and \code{False}, show that
it forms two (set-theoretical) monoids with respect to, respectively,
operator \code{\&\&} (AND) and \code{||} (OR).
\item
Represent the \code{Bool} monoid with the AND operator as a category: List
the morphisms and their rules of composition.
\item
Represent addition modulo 3 as a monoid category.
\end{enumerate}

View File

@ -110,8 +110,8 @@ that they piggyback a message string on top of their regular return
values.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/piggyback.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/piggyback.jpg}
\end{figure}
\noindent
We will ``embellish'' the return values of these functions. Let's do it
@ -156,7 +156,7 @@ Now imagine a whole program written in this style. It's a nightmare of
repetitive, error-prone code. But we are programmers. We know how to
deal with repetitive code: we abstract it! This is, however, not your
run of the mill abstraction --- we have to abstract \newterm{function
composition} itself. But composition is the essence of category theory,
composition} itself. But composition is the essence of category theory,
so before we write more code, let's analyze the problem from the
categorical point of view.
@ -205,18 +205,18 @@ So here's the recipe for the composition of two morphisms in this new
category we are constructing:
\begin{enumerate}
\tightlist
\item
Execute the embellished function corresponding to the first morphism
\item
Extract the first component of the result pair and pass it to the
embellished function corresponding to the second morphism
\item
Concatenate the second component (the string) of the first result
and the second component (the string) of the second result
\item
Return a new pair combining the first component of the final result
with the concatenated string.
\tightlist
\item
Execute the embellished function corresponding to the first morphism
\item
Extract the first component of the result pair and pass it to the
embellished function corresponding to the second morphism
\item
Concatenate the second component (the string) of the first result
and the second component (the string) of the second result
\item
Return a new pair combining the first component of the final result
with the concatenated string.
\end{enumerate}
If we want to abstract this composition as a higher order function in
@ -431,16 +431,16 @@ optional<double> safe_root(double x) {
Here's the challenge:
\begin{enumerate}
\tightlist
\item
Construct the Kleisli category for partial functions (define
composition and identity).
\item
Implement the embellished function \code{safe\_reciprocal} that
returns a valid reciprocal of its argument, if it's different from
zero.
\item
Compose the functions \code{safe\_root} and \code{safe\_reciprocal} to implement
\code{safe\_root\_reciprocal} that calculates \code{sqrt(1/x)}
whenever possible.
\tightlist
\item
Construct the Kleisli category for partial functions (define
composition and identity).
\item
Implement the embellished function \code{safe\_reciprocal} that
returns a valid reciprocal of its argument, if it's different from
zero.
\item
Compose the functions \code{safe\_root} and \code{safe\_reciprocal} to implement
\code{safe\_root\_reciprocal} that calculates \code{sqrt(1/x)}
whenever possible.
\end{enumerate}

View File

@ -45,13 +45,13 @@ or equal-to another object. Which leads us to this definition of the
initial object:
\begin{quote}
The \textbf{initial object} is the object that has one and only one
morphism going to any object in the category.
The \textbf{initial object} is the object that has one and only one
morphism going to any object in the category.
\end{quote}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/initial.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/initial.jpg}
\end{figure}
\noindent
@ -87,13 +87,13 @@ object that's more terminal than any other object in the category.
Again, we will insist on uniqueness:
\begin{quote}
The \textbf{terminal object} is the object with one and only one
morphism coming to it from any object in the category.
The \textbf{terminal object} is the object with one and only one
morphism coming to it from any object in the category.
\end{quote}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/final.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/final.jpg}
\end{figure}
\noindent
@ -192,9 +192,9 @@ $i_{2}$ to $i_{1}$. What's the composition of
these two morphisms?
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/uniqueness.jpg}
\caption{All morphisms in this diagram are unique.}
\centering
\includegraphics[width=0.4\textwidth]{images/uniqueness.jpg}
\caption{All morphisms in this diagram are unique.}
\end{figure}
\noindent
@ -259,8 +259,8 @@ respectively:
\src{snippet09}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/productpattern.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/productpattern.jpg}
\end{figure}
\noindent
@ -268,8 +268,8 @@ All $c$s that fit this pattern will be considered candidates for
the product. There may be lots of them.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/productcandidates.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/productcandidates.jpg}
\end{figure}
\noindent
@ -307,8 +307,8 @@ $p'$ and $q'$ can be reconstructed from $p$ and $q$ using $m$:
\src{snippet12}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/productranking.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/productranking.jpg}
\end{figure}
\noindent
@ -323,8 +323,8 @@ and \code{snd} is indeed \emph{better} than the two candidates I
presented before.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/not-a-product.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/not-a-product.jpg}
\end{figure}
\noindent
@ -375,10 +375,10 @@ category using the same universal construction. Such a product doesn't
always exist, but when it does, it is unique up to a unique isomorphism.
\begin{quote}
A \textbf{product} of two objects $a$ and $b$ is the object
$c$ equipped with two projections such that for any other object
$c'$ equipped with two projections there is a unique morphism
$m$ from $c'$ to $c$ that factorizes those projections.
A \textbf{product} of two objects $a$ and $b$ is the object
$c$ equipped with two projections such that for any other object
$c'$ equipped with two projections there is a unique morphism
$m$ from $c'$ to $c$ that factorizes those projections.
\end{quote}
\noindent
@ -399,8 +399,8 @@ and $b$ to $c$.
\src{snippet21}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/coproductpattern.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/coproductpattern.jpg}
\end{figure}
\noindent
@ -412,8 +412,8 @@ factorizes the injections:
\src{snippet22}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/coproductranking.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/coproductranking.jpg}
\end{figure}
\noindent
@ -422,10 +422,10 @@ any other pattern, is called a coproduct and, if it exists, is unique up
to unique isomorphism.
\begin{quote}
A \textbf{coproduct} of two objects $a$ and $b$ is the object
$c$ equipped with two injections such that for any other object
$c'$ equipped with two injections there is a unique morphism
$m$ from $c$ to $c'$ that factorizes those injections.
A \textbf{coproduct} of two objects $a$ and $b$ is the object
$c$ equipped with two injections such that for any other object
$c'$ equipped with two injections there is a unique morphism
$m$ from $c$ to $c'$ that factorizes those injections.
\end{quote}
\noindent
@ -588,41 +588,41 @@ isomorphism is the same as a bijection.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show that the terminal object is unique up to unique isomorphism.
\item
What is a product of two objects in a poset? Hint: Use the universal
construction.
\item
What is a coproduct of two objects in a poset?
\item
Implement the equivalent of Haskell \code{Either} as a generic type
in your favorite language (other than Haskell).
\item
Show that \code{Either} is a ``better'' coproduct than \code{int}
equipped with two injections:
\tightlist
\item
Show that the terminal object is unique up to unique isomorphism.
\item
What is a product of two objects in a poset? Hint: Use the universal
construction.
\item
What is a coproduct of two objects in a poset?
\item
Implement the equivalent of Haskell \code{Either} as a generic type
in your favorite language (other than Haskell).
\item
Show that \code{Either} is a ``better'' coproduct than \code{int}
equipped with two injections:
\begin{snip}{cpp}
\begin{snip}{cpp}
int i(int n) { return n; }
int j(bool b) { return b ? 0: 1; }
\end{snip}
Hint: Define a function
Hint: Define a function
\begin{snip}{cpp}
\begin{snip}{cpp}
int m(Either const & e);
\end{snip}
that factorizes \code{i} and \code{j}.
\item
Continuing the previous problem: How would you argue that \code{int}
with the two injections \code{i} and \code{j} cannot be ``better''
than \code{Either}?
\item
Still continuing: What about these injections?
that factorizes \code{i} and \code{j}.
\item
Continuing the previous problem: How would you argue that \code{int}
with the two injections \code{i} and \code{j} cannot be ``better''
than \code{Either}?
\item
Still continuing: What about these injections?
\begin{snip}{cpp}
\begin{snip}{cpp}
int i(int n) {
if (n < 0) return n;
return n + 2;
@ -630,18 +630,18 @@ int i(int n) {
int j(bool b) { return b ? 0: 1; }
\end{snip}
\item
Come up with an inferior candidate for a coproduct of \code{int} and
\code{bool} that cannot be better than \code{Either} because it
allows multiple acceptable morphisms from it to \code{Either}.
\item
Come up with an inferior candidate for a coproduct of \code{int} and
\code{bool} that cannot be better than \code{Either} because it
allows multiple acceptable morphisms from it to \code{Either}.
\end{enumerate}
\section{Bibliography}
\begin{enumerate}
\tightlist
\item
The Catsters,
\urlref{https://www.youtube.com/watch?v=upCSDIO9pjc}{Products and
Coproducts} video.
\tightlist
\item
The Catsters,
\urlref{https://www.youtube.com/watch?v=upCSDIO9pjc}{Products and
Coproducts} video.
\end{enumerate}

View File

@ -22,8 +22,8 @@ in C++ it's a relatively complex template defined in the Standard
Library.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/pair.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/pair.jpg}
\end{figure}
\noindent
@ -384,17 +384,17 @@ statements about, say, natural numbers, which form a rig, to statements
about types. Here's a translation table with some entries of interest:
\begin{longtable}[]{@{}ll@{}}
\toprule
Numbers & Types\tabularnewline
\midrule
\endhead
$0$ & \code{Void}\tabularnewline
$1$ & \code{()}\tabularnewline
$a + b$ & \code{Either a b = Left a | Right b}\tabularnewline
$a \times b$ & \code{(a, b)} or \code{Pair a b = Pair a b}\tabularnewline
$2 = 1 + 1$ & \code{data Bool = True | False}\tabularnewline
$1 + a$ & \code{data Maybe = Nothing | Just a}\tabularnewline
\bottomrule
\toprule
Numbers & Types\tabularnewline
\midrule
\endhead
$0$ & \code{Void}\tabularnewline
$1$ & \code{()}\tabularnewline
$a + b$ & \code{Either a b = Left a | Right b}\tabularnewline
$a \times b$ & \code{(a, b)} or \code{Pair a b = Pair a b}\tabularnewline
$2 = 1 + 1$ & \code{data Bool = True | False}\tabularnewline
$1 + a$ & \code{data Maybe = Nothing | Just a}\tabularnewline
\bottomrule
\end{longtable}
\noindent
@ -407,7 +407,7 @@ If we do our usual substitutions, and also replace \code{List a} with
\code{x}, we get the equation:
\begin{Verbatim}
x = 1 + a * x
x = 1 + a * x
\end{Verbatim}
We can't solve it using traditional algebraic methods because we can't
subtract or divide types. But we can try a series of substitutions,
@ -416,11 +416,11 @@ where we keep replacing \code{x} on the right hand side with
the following series:
\begin{Verbatim}
x = 1 + a*x
x = 1 + a*(1 + a*x) = 1 + a + a*a*x
x = 1 + a + a*a*(1 + a*x) = 1 + a + a*a + a*a*a*x
...
x = 1 + a + a*a + a*a*a + a*a*a*a...
x = 1 + a*x
x = 1 + a*(1 + a*x) = 1 + a + a*a*x
x = 1 + a + a*a*(1 + a*x) = 1 + a + a*a + a*a*a*x
...
x = 1 + a + a*a + a*a*a + a*a*a*a...
\end{Verbatim}
We end up with an infinite sum of products (tuples), which can be
interpreted as: A list is either empty, \code{1}; or a singleton,
@ -445,15 +445,15 @@ of them is inhabited. Logical \emph{and} and \emph{or} also form a
semiring, and it too can be mapped into type theory:
\begin{longtable}[]{@{}ll@{}}
\toprule
Logic & Types\tabularnewline
\midrule
\endhead
$\mathit{false}$ & \code{Void}\tabularnewline
$\mathit{true}$ & \code{()}\tabularnewline
$a \mathbin{||} b$ & \code{Either a b = Left a | Right b}\tabularnewline
$a \mathbin{\&\&} b$ & \code{(a, b)}\tabularnewline
\bottomrule
\toprule
Logic & Types\tabularnewline
\midrule
\endhead
$\mathit{false}$ & \code{Void}\tabularnewline
$\mathit{true}$ & \code{()}\tabularnewline
$a \mathbin{||} b$ & \code{Either a b = Left a | Right b}\tabularnewline
$a \mathbin{\&\&} b$ & \code{(a, b)}\tabularnewline
\bottomrule
\end{longtable}
\noindent
@ -464,47 +464,47 @@ talk about function types.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show the isomorphism between \code{Maybe a} and
\code{Either () a}.
\item
Here's a sum type defined in Haskell:
\tightlist
\item
Show the isomorphism between \code{Maybe a} and
\code{Either () a}.
\item
Here's a sum type defined in Haskell:
\begin{snip}{haskell}
\begin{snip}{haskell}
data Shape = Circle Float
| Rect Float Float
\end{snip}
When we want to define a function like \code{area} that acts on a
\code{Shape}, we do it by pattern matching on the two constructors:
When we want to define a function like \code{area} that acts on a
\code{Shape}, we do it by pattern matching on the two constructors:
\begin{snip}{haskell}
\begin{snip}{haskell}
area :: Shape -> Float
area (Circle r) = pi * r * r
area (Rect d h) = d * h
\end{snip}
Implement \code{Shape} in C++ or Java as an interface and create two
classes: \code{Circle} and \code{Rect}. Implement \code{area} as
a virtual function.
\item
Continuing with the previous example: We can easily add a new function
\code{circ} that calculates the circumference of a \code{Shape}.
We can do it without touching the definition of \code{Shape}:
Implement \code{Shape} in C++ or Java as an interface and create two
classes: \code{Circle} and \code{Rect}. Implement \code{area} as
a virtual function.
\item
Continuing with the previous example: We can easily add a new function
\code{circ} that calculates the circumference of a \code{Shape}.
We can do it without touching the definition of \code{Shape}:
\begin{snip}{haskell}
\begin{snip}{haskell}
circ :: Shape -> Float
circ (Circle r) = 2.0 * pi * r
circ (Rect d h) = 2.0 * (d + h)
\end{snip}
Add \code{circ} to your C++ or Java implementation. What parts of
the original code did you have to touch?
\item
Continuing further: Add a new shape, \code{Square}, to
\code{Shape} and make all the necessary updates. What code did you
have to touch in Haskell vs. C++ or Java? (Even if you're not a
Haskell programmer, the modifications should be pretty obvious.)
\item
Show that $a + a = 2 \times a$ holds for types (up to
isomorphism). Remember that $2$ corresponds to \code{Bool},
according to our translation table.
Add \code{circ} to your C++ or Java implementation. What parts of
the original code did you have to touch?
\item
Continuing further: Add a new shape, \code{Square}, to
\code{Shape} and make all the necessary updates. What code did you
have to touch in Haskell vs. C++ or Java? (Even if you're not a
Haskell programmer, the modifications should be pretty obvious.)
\item
Show that $a + a = 2 \times a$ holds for types (up to
isomorphism). Remember that $2$ corresponds to \code{Bool},
according to our translation table.
\end{enumerate}

View File

@ -21,7 +21,7 @@ makes sense by now. I won't use parentheses when applying functors to
objects or morphisms.)
\begin{figure}[H]
\centering\includegraphics[width=0.3\textwidth]{images/functor.jpg}
\centering\includegraphics[width=0.3\textwidth]{images/functor.jpg}
\end{figure}
\noindent
@ -36,8 +36,8 @@ and $g$:
\[F h = F g~.~F f\]
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/functorcompos.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/functorcompos.jpg}
\end{figure}
\noindent
@ -50,8 +50,8 @@ Here, $\idarrow[a]$ is the identity at the object $a$,
and $\idarrow[F a]$ the identity at $F a$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/functorid.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/functorid.jpg}
\end{figure}
\noindent
@ -124,8 +124,8 @@ signature:
\src{snippet04}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/functormaybe.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/functormaybe.jpg}
\end{figure}
\noindent
@ -707,23 +707,23 @@ We'll see later that functors form categories as well.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Can we turn the \code{Maybe} type constructor into a functor by
defining:
\tightlist
\item
Can we turn the \code{Maybe} type constructor into a functor by
defining:
\begin{snip}{haskell}
\begin{snip}{haskell}
fmap _ _ = Nothing
\end{snip}
which ignores both of its arguments? (Hint: Check the functor laws.)
\item
Prove functor laws for the reader functor. Hint: it's really simple.
\item
Implement the reader functor in your second favorite language (the
first being Haskell, of course).
\item
Prove the functor laws for the list functor. Assume that the laws are
true for the tail part of the list you're applying it to (in other
words, use \emph{induction}).
which ignores both of its arguments? (Hint: Check the functor laws.)
\item
Prove functor laws for the reader functor. Hint: it's really simple.
\item
Implement the reader functor in your second favorite language (the
first being Haskell, of course).
\item
Prove the functor laws for the list functor. Assume that the laws are
true for the tail part of the list you're applying it to (in other
words, use \emph{induction}).
\end{enumerate}

View File

@ -18,7 +18,7 @@ $\cat{E}$. Notice that this is just saying that it's a mapping from a
\newterm{Cartesian product} of categories $\cat{C}\times{}\cat{D}$ to $\cat{E}$.
\begin{figure}[H]
\centering\includegraphics[width=0.3\textwidth]{images/bifunctor.jpg}
\centering\includegraphics[width=0.3\textwidth]{images/bifunctor.jpg}
\end{figure}
\noindent
@ -52,8 +52,8 @@ constructor that takes two type arguments. Here's the definition of the
\src{snippet01}
\begin{figure}[H]
\centering\includegraphics[width=0.3\textwidth]{images/bimap.jpg}
\caption{bimap}
\centering\includegraphics[width=0.3\textwidth]{images/bimap.jpg}
\caption{bimap}
\end{figure}
The type variable \code{f} represents the bifunctor. You can see that
@ -76,14 +76,14 @@ first and the second argument, respectively.
\begin{figure}[H]
\centering
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=0.65\textwidth]{images/first.jpg} % first figure itself
\caption{first}
\centering
\includegraphics[width=0.65\textwidth]{images/first.jpg} % first figure itself
\caption{first}
\end{minipage}\hfill
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=0.6\textwidth]{images/second.jpg} % second figure itself
\caption{second}
\centering
\includegraphics[width=0.6\textwidth]{images/second.jpg} % second figure itself
\caption{second}
\end{minipage}
\end{figure}
@ -102,7 +102,7 @@ make sure they are related to each other in this manner).
An important example of a bifunctor is the categorical product --- a
product of two objects that is defined by a \hyperref[products-and-coproducts]{universal
construction}. If the product exists for any pair of objects, the
construction}. If the product exists for any pair of objects, the
mapping from those objects to the product is bifunctorial. This is true
in general, and in Haskell in particular. Here's the \code{Bifunctor}
instance for a pair constructor --- the simplest product type:
@ -362,7 +362,7 @@ This implementation can also be automatically derived by the compiler.
\section{The Writer Functor}
I promised that I would come back to the \hyperref[kleisli-categories]{Kleisli
category} I described earlier. Morphisms in that category were
category} I described earlier. Morphisms in that category were
represented as ``embellished'' functions returning the \code{Writer}
data structure.
@ -488,8 +488,8 @@ by the way --- the kind we've been studying thus far --- are called
\emph{covariant} functors.
\begin{figure}[H]
\centering
\includegraphics[width=40mm]{images/contravariant.jpg}
\centering
\includegraphics[width=40mm]{images/contravariant.jpg}
\end{figure}
\noindent
@ -538,9 +538,9 @@ the defaults for \code{lmap} and \code{rmap}, or implementing both
\code{dimap}.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/dimap.jpg}
\caption{dimap}
\centering
\includegraphics[width=0.4\textwidth]{images/dimap.jpg}
\caption{dimap}
\end{figure}
\noindent
@ -562,8 +562,8 @@ category $\cat{C}^{op}\times{}\cat{C}$ to the category of sets, $\Set$.
Let's define its action on morphisms. A morphism in
$\cat{C}^{op}\times{}\cat{C}$ is a pair of morphisms from $\cat{C}$:
\begin{gather*}
f \Colon a' \to a \\
g \Colon b \to b'
f \Colon a' \to a \\
g \Colon b \to b'
\end{gather*}
The lifting of this pair must be a morphism (a function) from the set
$\cat{C}(a, b)$ to the set $\cat{C}(a', b')$. Just pick
@ -577,48 +577,48 @@ As you can see, the hom-functor is a special case of a profunctor.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show that the data type:
\tightlist
\item
Show that the data type:
\begin{snip}{haskell}
\begin{snip}{haskell}
data Pair a b = Pair a b
\end{snip}
is a bifunctor. For additional credit implement all three methods of
\code{Bifunctor} and use equational reasoning to show that these
definitions are compatible with the default implementations whenever
they can be applied.
\item
Show the isomorphism between the standard definition of \code{Maybe}
and this desugaring:
is a bifunctor. For additional credit implement all three methods of
\code{Bifunctor} and use equational reasoning to show that these
definitions are compatible with the default implementations whenever
they can be applied.
\item
Show the isomorphism between the standard definition of \code{Maybe}
and this desugaring:
\begin{snip}{haskell}
\begin{snip}{haskell}
type Maybe' a = Either (Const () a) (Identity a)
\end{snip}
Hint: Define two mappings between the two implementations. For
additional credit, show that they are the inverse of each other using
equational reasoning.
\item
Let's try another data structure. I call it a \code{PreList} because
it's a precursor to a \code{List}. It replaces recursion with a type
parameter \code{b}.
Hint: Define two mappings between the two implementations. For
additional credit, show that they are the inverse of each other using
equational reasoning.
\item
Let's try another data structure. I call it a \code{PreList} because
it's a precursor to a \code{List}. It replaces recursion with a type
parameter \code{b}.
\begin{snip}{haskell}
\begin{snip}{haskell}
data PreList a b = Nil | Cons a b
\end{snip}
You could recover our earlier definition of a \code{List} by
recursively applying \code{PreList} to itself (we'll see how it's
done when we talk about fixed points).
You could recover our earlier definition of a \code{List} by
recursively applying \code{PreList} to itself (we'll see how it's
done when we talk about fixed points).
Show that \code{PreList} is an instance of \code{Bifunctor}.
\item
Show that the following data types define bifunctors in \code{a} and
\code{b}:
Show that \code{PreList} is an instance of \code{Bifunctor}.
\item
Show that the following data types define bifunctors in \code{a} and
\code{b}:
\begin{snip}{haskell}
\begin{snip}{haskell}
data K2 c a b = K2 c
data Fst a b = Fst a
@ -626,14 +626,14 @@ data Fst a b = Fst a
data Snd a b = Snd b
\end{snip}
For additional credit, check your solutions against Conor McBride's
paper \urlref{http://strictlypositive.org/CJ.pdf}{Clowns to the Left of
me, Jokers to the Right}.
\item
Define a bifunctor in a language other than Haskell. Implement
\code{bimap} for a generic pair in that language.
\item
Should \code{std::map} be considered a bifunctor or a profunctor in
the two template arguments \code{Key} and \code{T}? How would you
redesign this data type to make it so?
For additional credit, check your solutions against Conor McBride's
paper \urlref{http://strictlypositive.org/CJ.pdf}{Clowns to the Left of
me, Jokers to the Right}.
\item
Define a bifunctor in a language other than Haskell. Implement
\code{bimap} for a generic pair in that language.
\item
Should \code{std::map} be considered a bifunctor or a profunctor in
the two template arguments \code{Key} and \code{T}? How would you
redesign this data type to make it so?
\end{enumerate}

View File

@ -12,9 +12,9 @@ in the category $\Set$ every hom-set is itself an object in the
same category ---because it is, after all, a \emph{set}.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/set-hom-set.jpg}
\caption{Hom-set in Set is just a set}
\centering
\includegraphics[width=0.35\textwidth]{images/set-hom-set.jpg}
\caption{Hom-set in Set is just a set}
\end{figure}
\noindent
@ -22,9 +22,9 @@ The same is not true of other categories where hom-sets are external to
a category. They are even called \emph{external} hom-sets.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/hom-set.jpg}
\caption{Hom-set in category C is an external set}
\centering
\includegraphics[width=0.35\textwidth]{images/hom-set.jpg}
\caption{Hom-set in category C is an external set}
\end{figure}
\noindent
@ -46,7 +46,7 @@ relationship to the argument type and the result type. We've already
seen the constructions of composite types --- those that involved
relationships between objects. We used universal constructions to define
a \hyperref[products-and-coproducts]{product
and coproduct types}. We can use the same trick to define a
and coproduct types}. We can use the same trick to define a
function type. We will need a pattern that involves three objects: the
function type that we are constructing, the argument type, and the
result type.
@ -68,10 +68,10 @@ $f x$ (the application of $f$ to $x$, which is an
element of $b$).
\begin{figure}[H]
\centering\includegraphics[width=0.35\textwidth]{images/functionset.jpg}
\caption{In Set we can pick a function $f$ from a set of functions $z$ and we can
pick an argument $x$ from the set (type) $a$. We get an element $f x$ in the
set (type) $b$.}
\centering\includegraphics[width=0.35\textwidth]{images/functionset.jpg}
\caption{In Set we can pick a function $f$ from a set of functions $z$ and we can
pick an argument $x$ from the set (type) $a$. We get an element $f x$ in the
set (type) $b$.}
\end{figure}
\noindent
@ -86,10 +86,10 @@ So that's the pattern: a product of two objects $z$ and
$a$ connected to another object $b$ by a morphism $g$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/functionpattern.jpg}
\caption{A pattern of objects and morphisms that is the starting point of the
universal construction}
\centering
\includegraphics[width=0.4\textwidth]{images/functionpattern.jpg}
\caption{A pattern of objects and morphisms that is the starting point of the
universal construction}
\end{figure}
\noindent
@ -121,9 +121,9 @@ through the application of $g$. (Hint: Read this sentence while
looking at the picture.)
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/functionranking.jpg}
\caption{Establishing a ranking between candidates for the function object}
\centering
\includegraphics[width=0.4\textwidth]{images/functionranking.jpg}
\caption{Establishing a ranking between candidates for the function object}
\end{figure}
\noindent
@ -134,7 +134,7 @@ that has both $z'$ and $z$ crossed with $a$.
What we really need, given the mapping $h$ from $z'$
to $z$, is a mapping from $z' \times a$ to $z \times a$.
And now, after discussing the \hyperref[functoriality]{functoriality
of the product}, we know how to do it. Because the product itself is a
of the product}, we know how to do it. Because the product itself is a
functor (more precisely an endo-bi-functor), it's possible to lift pairs
of morphisms. In other words, we can define not only products of objects
but also products of morphisms.
@ -161,29 +161,29 @@ $eval$. This object is better than any other object according to
our ranking.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/universalfunctionobject.jpg}
\caption{The definition of the universal function object. This is the same
diagram as above, but now the object $a \Rightarrow b$ is \emph{universal}.}
\centering
\includegraphics[width=0.4\textwidth]{images/universalfunctionobject.jpg}
\caption{The definition of the universal function object. This is the same
diagram as above, but now the object $a \Rightarrow b$ is \emph{universal}.}
\end{figure}
\noindent
Formally:
\begin{longtable}[]{@{}l@{}}
\toprule
\begin{minipage}[t]{0.97\columnwidth}\raggedright\strut
A \emph{function object} from $a$ to $b$ is an object
$a \Rightarrow b$ together with the morphism
\[eval \Colon ((a \Rightarrow b) \times a) \to b\]
such that for any other object $z$ with a morphism
\[g \Colon z \times a \to b\]
there is a unique morphism
\[h \Colon z \to (a \Rightarrow b)\]
that factors $g$ through $eval$:
\[g = eval \circ (h \times \id)\]
\end{minipage}\tabularnewline
\bottomrule
\toprule
\begin{minipage}[t]{0.97\columnwidth}\raggedright\strut
A \emph{function object} from $a$ to $b$ is an object
$a \Rightarrow b$ together with the morphism
\[eval \Colon ((a \Rightarrow b) \times a) \to b\]
such that for any other object $z$ with a morphism
\[g \Colon z \times a \to b\]
there is a unique morphism
\[h \Colon z \to (a \Rightarrow b)\]
that factors $g$ through $eval$:
\[g = eval \circ (h \times \id)\]
\end{minipage}\tabularnewline
\bottomrule
\end{longtable}
\noindent
@ -365,13 +365,13 @@ such a category.
A Cartesian closed category must contain:
\begin{enumerate}
\tightlist
\item
The terminal object,
\item
A product of any pair of objects, and
\item
An exponential for any pair of objects.
\tightlist
\item
The terminal object,
\item
A product of any pair of objects, and
\item
An exponential for any pair of objects.
\end{enumerate}
If you consider an exponential as an iterated product (possibly
infinitely many times), then you can think of a Cartesian closed
@ -388,8 +388,8 @@ The terminal object and the product have their duals: the initial object
and the coproduct. A Cartesian closed category that also supports those
two, and in which product can be distributed over coproduct
\begin{gather*}
a \times (b + c) = a \times b + a \times c \\
(b + c) \times a = b \times a + c \times a
a \times (b + c) = a \times b + a \times c \\
(b + c) \times a = b \times a + c \times a
\end{gather*}
is called a \newterm{bicartesian closed} category. We'll see in the next
section that bicartesian closed categories, of which $\Set$ is a
@ -596,11 +596,11 @@ revolutionizing the world in more than one way.
\section{Bibliography}
\begin{enumerate}
\tightlist
\item
Ralph Hinze, Daniel W. H. James,
\urlref{http://www.cs.ox.ac.uk/ralf.hinze/publications/WGP10.pdf}{Reason
Isomorphically!}. This paper contains proofs of all those high-school
algebraic identities in category theory that I mentioned in this
chapter.
\tightlist
\item
Ralph Hinze, Daniel W. H. James,
\urlref{http://www.cs.ox.ac.uk/ralf.hinze/publications/WGP10.pdf}{Reason
Isomorphically!}. This paper contains proofs of all those high-school
algebraic identities in category theory that I mentioned in this
chapter.
\end{enumerate}

View File

@ -37,7 +37,7 @@ if we could find it, we would probably revolutionize our understanding
of the universe.
\begin{wrapfigure}{R}{0pt}
\includegraphics[width=0.5\textwidth]{images/asteroids.png}
\includegraphics[width=0.5\textwidth]{images/asteroids.png}
\end{wrapfigure}
Let me elaborate. There is a similar duality in physics, which either
@ -66,8 +66,8 @@ which is given by force divided by mass.
These are the direct encodings of the differential equations
corresponding to Newton's laws of motion:
\begin{align*}
F &= m \frac{dv}{dt} \\
v &= \frac{dx}{dt}
F & = m \frac{dv}{dt} \\
v & = \frac{dx}{dt}
\end{align*}
Similar methods may be applied to more complex problems, like the
propagation of electromagnetic fields using Maxwell's equations, or even
@ -93,14 +93,14 @@ then take a shortcut through water. The path of minimum time makes the
ray refract at the boundary of air and water, resulting in Snell's law
of refraction:
\begin{equation*}
\frac{sin(\theta_1)}{sin(\theta_2)} = \frac{v_1}{v_2}
\frac{sin(\theta_1)}{sin(\theta_2)} = \frac{v_1}{v_2}
\end{equation*}
where $v_1$ is the speed of light in the air and $v_2$ is
the speed of light in the water.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/snell.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/snell.jpg}
\end{figure}
\noindent
@ -116,8 +116,8 @@ minimize kinetic energy. Then it will speed up to go quickly through the
area of low potential energy.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/mortar.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/mortar.jpg}
\end{figure}
\noindent
@ -128,8 +128,8 @@ Feynman path integral between those states is used to calculate the
probability of transition.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/feynman.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/feynman.jpg}
\end{figure}
\noindent
@ -180,8 +180,8 @@ best such object --- it optimizes a certain property: the property of
factorizing the projections of other such objects.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/productranking.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/productranking.jpg}
\end{figure}
\noindent
@ -200,7 +200,7 @@ built in, rather than being defined by universal constructions; although
there have been attempts at creating categorical programming languages
(see, e.g.,
\urlref{http://web.sfc.keio.ac.jp/~hagino/thesis.pdf}{Tatsuya
Hagino's thesis}).
Hagino's thesis}).
Whether used directly or not, categorical definitions justify
pre-existing programming constructs, and give rise to new ones. Most

View File

@ -8,8 +8,8 @@ Now that we know more about \hyperref[functors]{functors} and
try.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/productpattern.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/productpattern.jpg}
\end{figure}
\noindent
@ -36,8 +36,8 @@ nothing can stop us from using categories more complex than $\cat{2}$
to define our patterns.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/two.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/two.jpg}
\end{figure}
\noindent
@ -52,8 +52,8 @@ done with $\Delta_c$. Remember, $\Delta_c$ maps all
objects into $c$ and all morphisms into $\idarrow[c]$.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/twodelta.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/twodelta.jpg}
\end{figure}
\noindent
@ -75,8 +75,8 @@ is trivially satisfied, because there are no morphisms (other than the
identities) in $\cat{2}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/productcone.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/productcone.jpg}
\end{figure}
\noindent
@ -99,8 +99,8 @@ morphisms connecting $c$ to the diagram: the image of $\cat{I}$
under $D$.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/cone.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/cone.jpg}
\end{figure}
\noindent
@ -114,13 +114,13 @@ the naturality square becomes a commuting triangle. The two arms of this
triangle are the components of the natural transformation.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/conenaturality.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/conenaturality.jpg}
\end{figure}
\noindent
So that's one cone. What we are interested in is the \newterm{universal
cone} --- just like we picked a universal object for our definition of a
cone} --- just like we picked a universal object for our definition of a
product.
There are many ways to go about it. For instance, we may define a
@ -139,19 +139,19 @@ instance:
\src{snippet01}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/productranking.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/productranking.jpg}
\end{figure}
This condition translates, in the general case, to the condition that
the triangles whose one side is the factorizing morphism all commute.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/conecommutativity.jpg}
\caption{The commuting triangle connecting two cones, with the factorizing
morphism $h$ (here, the lower cone is the universal one, with
$\Lim[D]$ as its apex)}
\centering
\includegraphics[width=0.35\textwidth]{images/conecommutativity.jpg}
\caption{The commuting triangle connecting two cones, with the factorizing
morphism $h$ (here, the lower cone is the universal one, with
$\Lim[D]$ as its apex)}
\end{figure}
\noindent
@ -231,8 +231,8 @@ Notice the inversion in the order of $c$ and $c'$
characteristic of a \emph{contravariant} functor.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/homsetmapping.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/homsetmapping.jpg}
\end{figure}
\noindent
@ -265,8 +265,8 @@ It's relatively easy to show that those components indeed add up to a
natural transformation.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/natmapping.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/natmapping.jpg}
\end{figure}
\noindent
@ -346,8 +346,8 @@ and two projections:
\src{snippet04}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/equalizercone.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/equalizercone.jpg}
\end{figure}
\noindent
@ -401,8 +401,8 @@ with
\src{snippet12}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/equilizerlimit.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/equilizerlimit.jpg}
\end{figure}
\noindent
@ -428,8 +428,8 @@ and three morphisms:
\src{snippet14}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/pullbackcone.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/pullbackcone.jpg}
\end{figure}
\noindent
@ -441,8 +441,8 @@ So we are only left with the following condition:
A pullback is a universal cone of this shape.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/pullbacklimit.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/pullbacklimit.jpg}
\end{figure}
\noindent
@ -490,8 +490,8 @@ overriding of methods. And, of course, there would be no pullback if
there is a name conflict between some methods of \code{B} and \code{C}.
\begin{figure}[H]
\centering
\includegraphics[width=0.25\textwidth]{images/classes.jpg}
\centering
\includegraphics[width=0.25\textwidth]{images/classes.jpg}
\end{figure}
\noindent
@ -551,9 +551,9 @@ morphism, which now flows from the universal co-cone to any other
co-cone.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/colimit.jpg}
\caption{Cocone with a factorizing morphism $h$ connecting two apexes.}
\centering
\includegraphics[width=0.35\textwidth]{images/colimit.jpg}
\caption{Cocone with a factorizing morphism $h$ connecting two apexes.}
\end{figure}
\noindent
@ -562,8 +562,8 @@ diagram generated by $\cat{2}$, the category we've used in the
definition of the product.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/coproductranking.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/coproductranking.jpg}
\end{figure}
\noindent
@ -582,7 +582,7 @@ $1\leftarrow2\rightarrow3$.
I said previously that functors come close to the idea of continuous
mappings of categories, in the sense that they never break existing
connections (morphisms). The actual definition of a \emph{continuous
functor} $F$ from a category $\cat{C}$ to $\cat{C'}$ includes the
functor} $F$ from a category $\cat{C}$ to $\cat{C'}$ includes the
requirement that the functor preserve limits. Every diagram $D$
in $\cat{C}$ can be mapped to a diagram $F \circ D$ in $\cat{C'}$ by
simply composing two functors. The continuity condition for $F$
@ -591,8 +591,8 @@ the diagram $F \circ D$ also has a limit, and it is equal to
$F (\Lim[D])$.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{images/continuity.jpg}
\centering
\includegraphics[width=0.6\textwidth]{images/continuity.jpg}
\end{figure}
\noindent
@ -650,23 +650,23 @@ poset).
\section{Challenges}
\begin{enumerate}
\tightlist
\item
How would you describe a pushout in the category of C++ classes?
\item
Show that the limit of the identity functor
$\mathbf{Id} \Colon \cat{C} \to \cat{C}$ is the initial object.
\item
Subsets of a given set form a category. A morphism in that category is
defined to be an arrow connecting two sets if the first is the subset
of the second. What is a pullback of two sets in such a category?
What's a pushout? What are the initial and terminal objects?
\item
Can you guess what a coequalizer is?
\item
Show that, in a category with a terminal object, a pullback towards
the terminal object is a product.
\item
Similarly, show that a pushout from an initial object (if one exists)
is the coproduct.
\tightlist
\item
How would you describe a pushout in the category of C++ classes?
\item
Show that the limit of the identity functor
$\mathbf{Id} \Colon \cat{C} \to \cat{C}$ is the initial object.
\item
Subsets of a given set form a category. A morphism in that category is
defined to be an arrow connecting two sets if the first is the subset
of the second. What is a pullback of two sets in such a category?
What's a pushout? What are the initial and terminal objects?
\item
Can you guess what a coequalizer is?
\item
Show that, in a category with a terminal object, a pullback towards
the terminal object is a product.
\item
Similarly, show that a pushout from an initial object (if one exists)
is the coproduct.
\end{enumerate}

View File

@ -43,8 +43,8 @@ $(b, b)$, and end up with the set
$\{e, a, b, (a, a), (a, b), (b, a), (b, b)\}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{images/bunnies.jpg}
\centering
\includegraphics[width=0.8\textwidth]{images/bunnies.jpg}
\end{figure}
\noindent
@ -63,7 +63,7 @@ This kind of construction, in which you keep generating all possible
combinations of elements, and perform the minimum number of
identifications --- just enough to uphold the laws --- is called a free
construction. What we have just done is to construct a \newterm{free
monoid} from the set of generators $\{a, b\}$.
monoid} from the set of generators $\{a, b\}$.
\section{Free Monoid in Haskell}
@ -186,8 +186,8 @@ collapse them). It will all be sorted out by the universal construction,
which will pick the best representative of this pattern.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-pattern.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-pattern.jpg}
\end{figure}
\noindent
@ -213,8 +213,8 @@ be mapped to a product of the corresponding two generators in the second
monoid, and so on.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-ranking.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-ranking.jpg}
\end{figure}
\noindent
@ -222,11 +222,11 @@ This ranking may be used to find the best candidate --- the free monoid.
Here's the definition:
\begin{quote}
We'll say that $m$ (together with the function $p$) is the
\textbf{free monoid} with the generators $x$ if and only if there
is a \emph{unique} morphism $h$ from $m$ to any other
monoid $n$ (together with the function $q$) that satisfies
the above factorization property.
We'll say that $m$ (together with the function $p$) is the
\textbf{free monoid} with the generators $x$ if and only if there
is a \emph{unique} morphism $h$ from $m$ to any other
monoid $n$ (together with the function $q$) that satisfies
the above factorization property.
\end{quote}
Incidentally, this answers our second question. The function
$U h$ is the one that has the power to collapse multiple
@ -242,30 +242,30 @@ We'll come back to free monoids when we talk about adjunctions.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
You might think (as I did, originally) that the requirement that a
homomorphism of monoids preserve the unit is redundant. After all, we
know that for all $a$
\tightlist
\item
You might think (as I did, originally) that the requirement that a
homomorphism of monoids preserve the unit is redundant. After all, we
know that for all $a$
\begin{snip}{text}
\begin{snip}{text}
h a * h e = h (a * e) = h a
\end{snip}
So $h e$ acts like a right unit (and, by analogy, as a left
unit). The problem is that $h a$, for all $a$ might
only cover a sub-monoid of the target monoid. There may be a ``true''
unit outside of the image of $h$. Show that an isomorphism
between monoids that preserves multiplication must automatically
preserve unit.
\item
Consider a monoid homomorphism from lists of integers with
concatenation to integers with multiplication. What is the image of
the empty list \code{{[}{]}}? Assume that all singleton lists are
mapped to the integers they contain, that is \code{{[}3{]}} is
mapped to 3, etc. What's the image of \code{{[}1, 2, 3, 4{]}}?
How many different lists map to the integer 12? Is there any other
homomorphism between the two monoids?
\item
What is the free monoid generated by a one-element set? Can you see
what it's isomorphic to?
So $h e$ acts like a right unit (and, by analogy, as a left
unit). The problem is that $h a$, for all $a$ might
only cover a sub-monoid of the target monoid. There may be a ``true''
unit outside of the image of $h$. Show that an isomorphism
between monoids that preserves multiplication must automatically
preserve unit.
\item
Consider a monoid homomorphism from lists of integers with
concatenation to integers with multiplication. What is the image of
the empty list \code{{[}{]}}? Assume that all singleton lists are
mapped to the integers they contain, that is \code{{[}3{]}} is
mapped to 3, etc. What's the image of \code{{[}1, 2, 3, 4{]}}?
How many different lists map to the integer 12? Is there any other
homomorphism between the two monoids?
\item
What is the free monoid generated by a one-element set? Can you see
what it's isomorphic to?
\end{enumerate}

View File

@ -58,8 +58,8 @@ fixed, $\cat{C}(a, x)$ will also vary in $\Set$. Thus we have a
mapping from $x$ to $\Set$.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{images/hom-set.jpg}
\centering
\includegraphics[width=0.45\textwidth]{images/hom-set.jpg}
\end{figure}
\noindent
@ -85,8 +85,8 @@ is a morphism going from $a$ to $y$. It is therefore a
member of $\cat{C}(a, y)$.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{images/hom-functor.jpg}
\centering
\includegraphics[width=0.45\textwidth]{images/hom-functor.jpg}
\end{figure}
\noindent
@ -297,36 +297,36 @@ explore alternative implementations that have practical value.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show that the hom-functors map identity morphisms in \emph{C} to
corresponding identity functions in $\Set$.
\item
Show that \code{Maybe} is not representable.
\item
Is the \code{Reader} functor representable?
\item
Using \code{Stream} representation, memoize a function that squares
its argument.
\item
Show that \code{tabulate} and \code{index} for \code{Stream} are
indeed the inverse of each other. (Hint: use induction.)
\item
The functor:
\tightlist
\item
Show that the hom-functors map identity morphisms in \emph{C} to
corresponding identity functions in $\Set$.
\item
Show that \code{Maybe} is not representable.
\item
Is the \code{Reader} functor representable?
\item
Using \code{Stream} representation, memoize a function that squares
its argument.
\item
Show that \code{tabulate} and \code{index} for \code{Stream} are
indeed the inverse of each other. (Hint: use induction.)
\item
The functor:
\begin{snip}{haskell}
\begin{snip}{haskell}
Pair a = Pair a a
\end{snip}
is representable. Can you guess the type that represents it? Implement
\code{tabulate} and \code{index}.
is representable. Can you guess the type that represents it? Implement
\code{tabulate} and \code{index}.
\end{enumerate}
\section{Bibliography}
\begin{enumerate}
\tightlist
\item
The Catsters video about
\urlref{https://www.youtube.com/watch?v=4QgjKUzyrhM}{representable
functors}.
\tightlist
\item
The Catsters video about
\urlref{https://www.youtube.com/watch?v=4QgjKUzyrhM}{representable
functors}.
\end{enumerate}

View File

@ -50,13 +50,13 @@ $\alpha$. Because we are operating in $\Set$, the components of
the natural transformation, like $\alpha_x$ or $\alpha_y$, are just
regular functions between sets:
\begin{gather*}
\alpha_x \Colon \cat{C}(a, x) \to F x \\
\alpha_y \Colon \cat{C}(a, y) \to F y
\alpha_x \Colon \cat{C}(a, x) \to F x \\
\alpha_y \Colon \cat{C}(a, y) \to F y
\end{gather*}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda1.png}
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda1.png}
\end{figure}
\noindent
@ -79,8 +79,8 @@ Just how strong this condition is can be seen by specializing it to the
case of $x = a$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda2.png}
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda2.png}
\end{figure}
\noindent
@ -102,8 +102,8 @@ get a point in $F a$.
We have just proven the Yoneda lemma:
\begin{quote}
There is a one-to-one correspondence between natural transformations
from $\cat{C}(a, -)$ to $F$ and elements of $F a$.
There is a one-to-one correspondence between natural transformations
from $\cat{C}(a, -)$ to $F$ and elements of $F a$.
\end{quote}
in other words,
\[\cat{Nat}(\cat{C}(a, -), F) \cong F a\]
@ -133,8 +133,8 @@ $p$ to some point $q$ in $F a$. I'll show you that
any choice of $q$ leads to a unique natural transformation.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/yoneda3.png}
\centering
\includegraphics[width=0.3\textwidth]{images/yoneda3.png}
\end{figure}
\noindent
@ -149,8 +149,8 @@ hom-functor, the morphism $g$ is mapped to a function
$\cat{C}(a, g)$; and under $F$ it's mapped to $F g$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda4.png}
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda4.png}
\end{figure}
\noindent
@ -186,8 +186,8 @@ Since $p'$ was arbitrary, the whole function $\alpha_x$ is
thus determined.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda5.png}
\centering
\includegraphics[width=0.4\textwidth]{images/yoneda5.png}
\end{figure}
\noindent
@ -315,35 +315,35 @@ called the Yoneda lemma.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show that the two functions \code{phi} and \code{psi} that form
the Yoneda isomorphism in Haskell are inverses of each other.
\tightlist
\item
Show that the two functions \code{phi} and \code{psi} that form
the Yoneda isomorphism in Haskell are inverses of each other.
\begin{snip}{haskell}
\begin{snip}{haskell}
phi :: (forall x . (a -> x) -> F x) -> F a
phi alpha = alpha id
psi :: F a -> (forall x . (a -> x) -> F x)
psi fa h = fmap h fa
\end{snip}
\item
A discrete category is one that has objects but no morphisms other
than identity morphisms. How does the Yoneda lemma work for functors
from such a category?
\item
A list of units \code{{[}(){]}} contains no other information but
its length. So, as a data type, it can be considered an encoding of
integers. An empty list encodes zero, a singleton \code{{[}(){]}} (a
value, not a type) encodes one, and so on. Construct another
representation of this data type using the Yoneda lemma for the list
functor.
\item
A discrete category is one that has objects but no morphisms other
than identity morphisms. How does the Yoneda lemma work for functors
from such a category?
\item
A list of units \code{{[}(){]}} contains no other information but
its length. So, as a data type, it can be considered an encoding of
integers. An empty list encodes zero, a singleton \code{{[}(){]}} (a
value, not a type) encodes one, and so on. Construct another
representation of this data type using the Yoneda lemma for the list
functor.
\end{enumerate}
\section{Bibliography}
\begin{enumerate}
\tightlist
\item
\urlref{https://www.youtube.com/watch?v=TLMxHB19khE}{Catsters} video.
\tightlist
\item
\urlref{https://www.youtube.com/watch?v=TLMxHB19khE}{Catsters} video.
\end{enumerate}

View File

@ -15,11 +15,11 @@ It's a mapping of objects from category $\cat{C}$ to functors, which are
\emph{objects} in the functor category (see the section about functor
categories in
\hyperref[natural-transformations]{Natural
Transformations}). Let's use the notation $[\cat{C}, \Set]$ for the
Transformations}). Let's use the notation $[\cat{C}, \Set]$ for the
functor category from $\cat{C}$ to $\Set$. You may also recall that
hom-functors are the prototypical
\hyperref[representable-functors]{representable
functors}.
functors}.
Every time we have a mapping of objects between two categories, it's
natural to ask if such a mapping is also a functor. In other words
@ -41,8 +41,8 @@ and replace the generic $F$ with the hom-functor
$\cat{C}(b, -)$. We get:
\[[\cat{C}, \Set](\cat{C}(a, -), \cat{C}(b, -)) \cong \cat{C}(b, a)\]
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{images/yoneda-embedding.jpg}
\centering
\includegraphics[width=0.6\textwidth]{images/yoneda-embedding.jpg}
\end{figure}
\noindent
@ -53,8 +53,8 @@ $\cat{C}(b, a)$ --- that goes in the ``wrong'' direction. But that's
okay; it only means that the functor we are looking at is contravariant.
\begin{figure}[H]
\centering
\includegraphics[width=0.65\textwidth]{images/yoneda-embedding-2.jpg}
\centering
\includegraphics[width=0.65\textwidth]{images/yoneda-embedding-2.jpg}
\end{figure}
\noindent
@ -105,7 +105,7 @@ hom-set, $\cat{C}(-, a)$. That would give us a contravariant
hom-functor. Contravariant functors from $\cat{C}$ to $\Set$ are
our familiar presheaves (see, for instance,
\hyperref[limits-and-colimits]{Limits
and Colimits}). The co-Yoneda embedding defines the embedding of a
and Colimits}). The co-Yoneda embedding defines the embedding of a
category $\cat{C}$ in the category of presheaves. Its action on morphisms
is given by:
\[[\cat{C}, \Set](\cat{C}(-, a), \cat{C}(-, b)) \cong \cat{C}(a, b)\]
@ -275,23 +275,23 @@ to go wrong.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Express the co-Yoneda embedding in Haskell.
\item
Show that the bijection we established between \code{fromY} and
\code{btoa} is an isomorphism (the two mappings are the inverse of
each other).
\item
Work out the Yoneda embedding for a monoid. What functor corresponds
to the monoid's single object? What natural transformations correspond
to monoid morphisms?
\item
What is the application of the \emph{covariant} Yoneda embedding to
preorders? (Question suggested by Gershom Bazerman.)
\item
Yoneda embedding can be used to embed an arbitrary functor category
$[\cat{C}, \cat{D}]$ in the functor category
$[[\cat{C}, \cat{D}], \Set]$. Figure out how it works on morphisms
(which in this case are natural transformations).
\tightlist
\item
Express the co-Yoneda embedding in Haskell.
\item
Show that the bijection we established between \code{fromY} and
\code{btoa} is an isomorphism (the two mappings are the inverse of
each other).
\item
Work out the Yoneda embedding for a monoid. What functor corresponds
to the monoid's single object? What natural transformations correspond
to monoid morphisms?
\item
What is the application of the \emph{covariant} Yoneda embedding to
preorders? (Question suggested by Gershom Bazerman.)
\item
Yoneda embedding can be used to embed an arbitrary functor category
$[\cat{C}, \cat{D}]$ in the functor category
$[[\cat{C}, \cat{D}], \Set]$. Figure out how it works on morphisms
(which in this case are natural transformations).
\end{enumerate}

View File

@ -38,8 +38,8 @@ $c$, together with a pair of morphisms $p$ and $q$,
that has the universal property of being their product.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/productranking.jpg}
\centering
\includegraphics[width=0.3\textwidth]{images/productranking.jpg}
\end{figure}
\noindent
@ -59,8 +59,8 @@ functors $F$ and $G$. The other sides are the components
of the natural transformation (which are also morphisms).
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/3_naturality.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/3_naturality.jpg}
\end{figure}
\noindent
@ -77,8 +77,8 @@ transformation maps one such sheet corresponding to F, to another,
corresponding to G.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/sheets.png}
\centering
\includegraphics[width=0.35\textwidth]{images/sheets.png}
\end{figure}
\noindent
@ -204,15 +204,15 @@ empty. We can visualize a general category as a ``thick'' preorder.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Consider some degenerate cases of a naturality condition and draw the
appropriate diagrams. For instance, what happens if either functor
$F$ or $G$ map both objects $a$ and $b$
(the ends of $f \Colon a \to b$) to the same
object, e.g., $F a = F b$ or $G a = G b$?
(Notice that you get a cone or a co-cone this way.) Then consider
cases where either $F a = G a$ or $F b = G b$.
Finally, what if you start with a morphism that loops on itself ---
$f \Colon a \to a$?
\tightlist
\item
Consider some degenerate cases of a naturality condition and draw the
appropriate diagrams. For instance, what happens if either functor
$F$ or $G$ map both objects $a$ and $b$
(the ends of $f \Colon a \to b$) to the same
object, e.g., $F a = F b$ or $G a = G b$?
(Notice that you get a cone or a co-cone this way.) Then consider
cases where either $F a = G a$ or $F b = G b$.
Finally, what if you start with a morphism that loops on itself ---
$f \Colon a \to a$?
\end{enumerate}

View File

@ -77,8 +77,8 @@ family of morphisms:
for which the following diagram commutes, for any $f \Colon a \to b$:
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/end.jpg}
\centering
\includegraphics[width=0.35\textwidth]{images/end.jpg}
\end{figure}
\noindent
@ -89,8 +89,8 @@ from two naturality squares and one functoriality condition (profunctor
$q$ preserving composition):
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/end-1.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/end-1.jpg}
\end{figure}
\noindent
@ -126,8 +126,8 @@ $p\ a\ b$. We therefore insist that the following diagram
commute:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/end-2.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/end-2.jpg}
\end{figure}
\noindent
@ -144,8 +144,8 @@ $h \Colon a \to e$ that makes all triangles commute:
\[\pi_a \circ h = \alpha_a\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/end-21.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/end-21.jpg}
\end{figure}
\noindent
@ -245,8 +245,8 @@ is a profunctor, so it makes sense to study its end. This is the wedge
condition:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/end1.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/end1.jpg}
\end{figure}
\noindent
@ -254,8 +254,8 @@ Let's just pick one element from the set $\int_c \cat{C}(F\ c, G\ c)$.
The two projections will map this element to two components of a
particular transformation, let's call them:
\begin{align*}
\tau_a &\Colon F\ a \to G\ a \\
\tau_b &\Colon F\ b \to G\ b
\tau_a & \Colon F\ a \to G\ a \\
\tau_b & \Colon F\ b \to G\ b
\end{align*}
In the left branch, we lift a pair of morphisms
$\langle \idarrow[a], G\ f \rangle$ using the hom-functor. You
@ -273,9 +273,9 @@ from a dual to a wedge called a cowedge (pronounced co-wedge, not
cow-edge).
\begin{figure}[H]
\centering
\includegraphics[width=0.25\textwidth]{images/end-31.jpg}
\caption{An edgy cow?}
\centering
\includegraphics[width=0.25\textwidth]{images/end-31.jpg}
\caption{An edgy cow?}
\end{figure}
\noindent
@ -336,9 +336,9 @@ known as taking a quotient. To define a quotient we need an
\newterm{equivalence relation} $\sim$, a relation that
is reflexive, symmetric, and transitive:
\begin{align*}
&a \sim a \\
&\text{if}\ a \sim b\ \text{then}\ b \sim a \\
&\text{if}\ a \sim b\ \text{and}\ b \sim c\ \text{then}\ a \sim c
& a \sim a \\
& \text{if}\ a \sim b\ \text{then}\ b \sim a \\
& \text{if}\ a \sim b\ \text{and}\ b \sim c\ \text{then}\ a \sim c
\end{align*}
Such a relation splits the set into equivalence classes. Each class
consists of elements that are related to each other. We form a quotient

View File

@ -16,8 +16,8 @@ category $\cat{I}$ to $\cat{C}$. This is the functor that selects the base
of the cone --- the diagram functor.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan2.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan2.jpg}
\end{figure}
\noindent
@ -29,8 +29,8 @@ morphism. Any functor $F$ from $\cat{1}$ to $\cat{C}$ picks a
potential apex for our cone.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan15.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan15.jpg}
\end{figure}
\noindent
@ -40,8 +40,8 @@ our original $\Delta_c$. The following diagram shows this
transformation.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan3-e1492120491591.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan3-e1492120491591.jpg}
\end{figure}
\noindent
@ -59,8 +59,8 @@ transformation $\varepsilon'$ from $F' \circ K$ to
$D$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan31-e1492120512209.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan31-e1492120512209.jpg}
\end{figure}
\noindent
@ -74,8 +74,8 @@ on $K$). This transformation is then vertically composed with
$\varepsilon$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan5.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan5.jpg}
\end{figure}
\noindent
@ -108,8 +108,8 @@ that factorizes $\varepsilon'$:
This is quite a mouthful, but it can be visualized in this nice diagram:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan7.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan7.jpg}
\end{figure}
\noindent
@ -133,8 +133,8 @@ just half of it, namely a one-way natural transformation $\varepsilon$ from
$F \circ K$ to $D$. (The left Kan extension picks the other direction.)
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan6.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan6.jpg}
\end{figure}
\noindent
@ -158,8 +158,8 @@ transformation we called $\varepsilon'$ corresponds a unique natural
transformation we called $\sigma$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan92.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan92.jpg}
\end{figure}
\noindent
@ -205,8 +205,8 @@ cocone by using the functor $D \Colon \cat{I} \to \cat{C}$ to form its
base, and the functor $F \Colon \cat{1} \to \cat{C}$ to select its apex.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan81.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan81.jpg}
\end{figure}
\noindent
@ -214,8 +214,8 @@ The sides of the cocone, the injections, are components of a natural
transformation $\eta$ from $D$ to $F \circ K$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan10a.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan10a.jpg}
\end{figure}
\noindent
@ -224,16 +224,16 @@ $F'$ and a natural transformation
\[\eta' \Colon D \to F' \circ K\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan10b.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan10b.jpg}
\end{figure}
\noindent
there is a unique natural transformation $\sigma$ from $F$ to $F'$
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan14.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan14.jpg}
\end{figure}
\noindent
@ -242,8 +242,8 @@ such that:
This is illustrated in the following diagram:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan112.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan112.jpg}
\end{figure}
\noindent
@ -252,8 +252,8 @@ definition naturally generalized to the definition of the left Kan
extension, denoted by $\Lan_{K}D$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan12.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan12.jpg}
\end{figure}
\noindent
@ -300,8 +300,8 @@ hom-functor:
\[\cat{A}(a, K\ -)\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/kan13.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/kan13.jpg}
\end{figure}
\noindent
@ -423,15 +423,15 @@ Notice that, as described earlier in the general case, we performed the
following steps:
\begin{enumerate}
\tightlist
\item
Retrieved the container of \code{x} (here, it's
just a trivial identity container), and the function \code{f}.
\item
Repackaged the container using the natural transformation between the
identity functor and the pair functor.
\item
Called the function \code{f}.
\tightlist
\item
Retrieved the container of \code{x} (here, it's
just a trivial identity container), and the function \code{f}.
\item
Repackaged the container using the natural transformation between the
identity functor and the pair functor.
\item
Called the function \code{f}.
\end{enumerate}
\section{Free Functor}
@ -469,7 +469,7 @@ recording both the function and its argument. It accumulates the lifted
functions by recording their composition. Functor rules are
automatically satisfied. This construction was used in a paper
\urlref{http://okmij.org/ftp/Haskell/extensible/more.pdf}{Freer Monads,
More Extensible Effects}.
More Extensible Effects}.
Alternatively, we can use the right Kan extension for the same purpose:

View File

@ -84,37 +84,37 @@ that serves as the unit of the tensor product; again, up to natural
isomorphism. The two isomorphisms are called, respectively, the left and
the right unitor, and their components are:
\begin{align*}
\lambda_a &\Colon i \otimes a \to a \\
\rho_a &\Colon a \otimes i \to a
\lambda_a & \Colon i \otimes a \to a \\
\rho_a & \Colon a \otimes i \to a
\end{align*}
The associator and the unitors must satisfy coherence conditions:
\begin{figure}[H]
\centering
\begin{tikzcd}[row sep=large]
((a \otimes b) \otimes c) \otimes d
\arrow[d, "\alpha_{(a \otimes b)cd}"]
\arrow[rr, "\alpha_{abc} \otimes \id_d"]
& & (a \otimes (b \otimes c)) \otimes d
\arrow[d, "\alpha_{a(b \otimes c)d}"] \\
(a \otimes b) \otimes (c \otimes d)
\arrow[rd, "\alpha_{ab(c \otimes d)}"]
& & a \otimes ((b \otimes c) \otimes d)
\arrow[ld, "\id_a \otimes \alpha_{bcd}"] \\
& a \otimes (b \otimes (c \otimes d))
\end{tikzcd}
\centering
\begin{tikzcd}[row sep=large]
((a \otimes b) \otimes c) \otimes d
\arrow[d, "\alpha_{(a \otimes b)cd}"]
\arrow[rr, "\alpha_{abc} \otimes \id_d"]
& & (a \otimes (b \otimes c)) \otimes d
\arrow[d, "\alpha_{a(b \otimes c)d}"] \\
(a \otimes b) \otimes (c \otimes d)
\arrow[rd, "\alpha_{ab(c \otimes d)}"]
& & a \otimes ((b \otimes c) \otimes d)
\arrow[ld, "\id_a \otimes \alpha_{bcd}"] \\
& a \otimes (b \otimes (c \otimes d))
\end{tikzcd}
\end{figure}
\begin{figure}[H]
\centering
\begin{tikzcd}[row sep=large]
(a \otimes i) \otimes b
\arrow[dr, "\rho_{a} \otimes \id_b"']
\arrow[rr, "\alpha_{aib}"]
& & a \otimes (i \otimes b)
\arrow[dl, "\id_a \otimes \lambda_b"] \\
& a \otimes b
\end{tikzcd}
\centering
\begin{tikzcd}[row sep=large]
(a \otimes i) \otimes b
\arrow[dr, "\rho_{a} \otimes \id_b"']
\arrow[rr, "\alpha_{aib}"]
& & a \otimes (i \otimes b)
\arrow[dl, "\id_a \otimes \lambda_b"] \\
& a \otimes b
\end{tikzcd}
\end{figure}
\noindent
@ -135,7 +135,7 @@ that defines the internal hom in a monoidal category:
\[\cat{V}(a \otimes b, c) \sim \cat{V}(a, [b, c])\]
Following
\urlref{http://www.tac.mta.ca/tac/reprints/articles/10/tr10.pdf}{G. M.
Kelly}, I'm using the notation ${[}b, c{]}$ for the internal
Kelly}, I'm using the notation ${[}b, c{]}$ for the internal
hom. The counit of this adjunction is the natural transformation whose
components are called evaluation morphisms:
\[\varepsilon_{a b} \Colon ([a, b] \otimes a) \to b\]
@ -164,8 +164,8 @@ of morphisms is replaced by a family of morphisms in $\cat{V}$:
\[\circ \Colon \cat{C}(b, c) \otimes \cat{C}(a, b) \to \cat{C}(a, c)\]
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{images/composition.jpg}
\centering
\includegraphics[width=0.45\textwidth]{images/composition.jpg}
\end{figure}
\noindent
@ -175,8 +175,8 @@ $\cat{V}$:
where $i$ is the tensor unit in $\cat{V}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/id.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/id.jpg}
\end{figure}
\noindent
@ -184,19 +184,19 @@ Associativity of composition is defined in terms of the associator in
$\cat{V}$:
\begin{figure}[H]
\centering
\begin{tikzcd}[column sep=large]
(\cat{C}(c,d) \otimes \cat{C}(b,c)) \otimes \cat{C}(a,b)
\arrow[r, "\circ\otimes\id"]
\arrow[dd, "\alpha"]
& \cat{C}(b,d) \otimes \cat{C}(a,b)
\centering
\begin{tikzcd}[column sep=large]
(\cat{C}(c,d) \otimes \cat{C}(b,c)) \otimes \cat{C}(a,b)
\arrow[r, "\circ\otimes\id"]
\arrow[dd, "\alpha"]
& \cat{C}(b,d) \otimes \cat{C}(a,b)
\arrow[dr, "\circ"] \\
& & \cat{C}(a,d) \\
\cat{C}(c,d) \otimes (\cat{C}(b,c) \otimes \cat{C}(a,b))
\arrow[r, "\id\otimes\circ"]
& \cat{C}(c,d) \otimes \cat{C}(a,c)
& & \cat{C}(a,d) \\
\cat{C}(c,d) \otimes (\cat{C}(b,c) \otimes \cat{C}(a,b))
\arrow[r, "\id\otimes\circ"]
& \cat{C}(c,d) \otimes \cat{C}(a,c)
\arrow[ur, "\circ"]
\end{tikzcd}
\end{tikzcd}
\end{figure}
\noindent
@ -210,9 +210,9 @@ Unit laws are likewise expressed in terms of unitors:
\cat{C}(a,b) \otimes i
\arrow[rr, "\id \otimes j_a"]
\arrow[dr, "\rho"]
& & \cat{C}(a,b) \otimes \cat{C}(a,a)
\arrow[dl, "\circ"] \\
& \cat{C}(a,b)
& & \cat{C}(a,b) \otimes \cat{C}(a,a)
\arrow[dl, "\circ"] \\
& \cat{C}(a,b)
\end{tikzcd}
\end{subfigure}
\hspace{1cm}
@ -222,9 +222,9 @@ Unit laws are likewise expressed in terms of unitors:
i \otimes \cat{C}(a,b)
\arrow[rr, "j_b \otimes \id"]
\arrow[dr, "\lambda"]
& & \cat{C}(b,b) \otimes \cat{C}(a,b)
\arrow[dl, "\circ"] \\
& \cat{C}(a,b)
& & \cat{C}(b,b) \otimes \cat{C}(a,b)
\arrow[dl, "\circ"] \\
& \cat{C}(a,b)
\end{tikzcd}
\end{subfigure}
\end{figure}
@ -271,7 +271,7 @@ enforced, if we implement a preorder as an enriched category.
An interesting example is due to
\urlref{http://www.tac.mta.ca/tac/reprints/articles/1/tr1.pdf}{William
Lawvere}. He noticed that metric spaces can be defined using enriched
Lawvere}. He noticed that metric spaces can be defined using enriched
categories. A metric space defines a distance between any two objects.
This distance is a non-negative real number. It's convenient to include
infinity as a possible value. If the distance is infinite, there is no
@ -344,17 +344,17 @@ meant preserving composition and identity. In the enriched setting, the
preservation of composition means that the following diagram commute:
\begin{figure}[H]
\centering
\begin{tikzcd}[column sep=large, row sep=large]
\cat{C}(b,c) \otimes \cat{C}(a,b)
\arrow[r, "\circ"]
\arrow[d, "F_{bc} \otimes F_{ab}"]
\centering
\begin{tikzcd}[column sep=large, row sep=large]
\cat{C}(b,c) \otimes \cat{C}(a,b)
\arrow[r, "\circ"]
\arrow[d, "F_{bc} \otimes F_{ab}"]
& \cat{C}(a,c)
\arrow[d, "F_{ac}"] \\
\cat{D}(F\ b, F\ c) \otimes \cat{D}(F\ a, F\ b)
\arrow[r, "\circ"]
\arrow[d, "F_{ac}"] \\
\cat{D}(F\ b, F\ c) \otimes \cat{D}(F\ a, F\ b)
\arrow[r, "\circ"]
& \cat{D}(F\ a, F\ c)
\end{tikzcd}
\end{tikzcd}
\end{figure}
\noindent
@ -362,13 +362,13 @@ The preservation of identity is replaced by the preservation of the
morphisms in $\cat{V}$ that ``select'' the identity:
\begin{figure}[H]
\centering
\begin{tikzcd}[row sep=large]
\centering
\begin{tikzcd}[row sep=large]
& i \arrow[dl, "j_a"'] \arrow[dr, "j_{F a}"] & \\
\cat{C}(a,a)
\arrow[rr, "F_{aa}"]
\cat{C}(a,a)
\arrow[rr, "F_{aa}"]
& & \cat{D}(F\ a, F\ a)
\end{tikzcd}
\end{tikzcd}
\end{figure}
\section{Self Enrichment}

View File

@ -52,8 +52,8 @@ to be isomorphic to $a$. We can use this fact to define a subset
as a family of injective functions that are related by isomorphisms of
their domains. More precisely, we say that two injective functions:
\begin{align*}
f &\Colon a \to b \\
f' &\Colon a' \to b
f & \Colon a \to b \\
f' & \Colon a' \to b
\end{align*}
are equivalent if there is an isomorphism:
\[h \Colon a \to a'\]
@ -62,8 +62,8 @@ such that:
Such a family of equivalent injections defines a subset of $b$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/subsetinjection.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/subsetinjection.jpg}
\end{figure}
\noindent
@ -72,16 +72,16 @@ injective functions with monomorphism. Just to remind you, a
monomorphism $m$ from $a$ to $b$ is defined by its
universal property. For any object $c$ and any pair of morphisms:
\begin{align*}
g &\Colon c \to a \\
g' &\Colon c \to a
g & \Colon c \to a \\
g' & \Colon c \to a
\end{align*}
such that:
\[m\ .\ g = m\ .\ g'\]
it must be that $g = g'$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/monomorphism.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/monomorphism.jpg}
\end{figure}
\noindent
@ -93,8 +93,8 @@ $g'$ that differ only at those two elements. The
postcomposition with $m$ would then mask this difference.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/notmono.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/notmono.jpg}
\end{figure}
\noindent
@ -112,8 +112,8 @@ $true$:
\[true \Colon 1 \to \Omega\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/true.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/true.jpg}
\end{figure}
\noindent
@ -136,8 +136,8 @@ and the injective function that embeds it in $b$. Here's the
pullback diagram:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/pullback.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/pullback.jpg}
\end{figure}
\noindent
@ -197,14 +197,14 @@ representation is the object $\Omega$.
A topos is a category that:
\begin{enumerate}
\tightlist
\item
Is Cartesian closed: It has all products, the terminal object, and
exponentials (defined as right adjoints to products),
\item
Has limits for all finite diagrams,
\item
Has a subobject classifier $\Omega$.
\tightlist
\item
Is Cartesian closed: It has all products, the terminal object, and
exponentials (defined as right adjoints to products),
\item
Has limits for all finite diagrams,
\item
Has a subobject classifier $\Omega$.
\end{enumerate}
This set of properties makes a topos a shoe-in for $\Set$ in most
@ -251,8 +251,8 @@ logics.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Show that the function $f$ that is the pullback of
$true$ along the characteristic function must be injective.
\tightlist
\item
Show that the function $f$ that is the pullback of
$true$ along the characteristic function must be injective.
\end{enumerate}

View File

@ -52,23 +52,23 @@ The derivation of Lawvere theories goes through many steps, so here's
the roadmap:
\begin{enumerate}
\tightlist
\item
Category of finite sets $\cat{FinSet}$.
\item
Its skeleton $\cat{F}$.
\item
Its opposite $\Fop$.
\item
Lawvere theory $\cat{L}$: an object in the category $\cat{Law}$.
\item
Model $M$ of a Lawvere category: an object in the category\\
$\cat{Mod}(\cat{Law}, \Set)$.
\tightlist
\item
Category of finite sets $\cat{FinSet}$.
\item
Its skeleton $\cat{F}$.
\item
Its opposite $\Fop$.
\item
Lawvere theory $\cat{L}$: an object in the category $\cat{Law}$.
\item
Model $M$ of a Lawvere category: an object in the category\\
$\cat{Mod}(\cat{Law}, \Set)$.
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{images/lawvere1.png}
\centering
\includegraphics[width=0.8\textwidth]{images/lawvere1.png}
\end{figure}
\section{Lawvere Theories}
@ -112,7 +112,7 @@ corresponding to all $n$-element sets in $\cat{FinSet}$ that have been
identified through isomorphisms.
Using the category $\cat{F}$ we can formally define a \newterm{Lawvere
theory} as a category $\cat{L}$ equipped with a special functor:
theory} as a category $\cat{L}$ equipped with a special functor:
\[I_{\cat{L}} \Colon \Fop \to \cat{L}\]
This functor must be a bijection on objects and it must preserve finite
products (products in $\Fop$ are the same as
@ -162,12 +162,12 @@ functions (or, as we've seen earlier, that the hom-functor is
continuous).
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{images/lawvere1.png}
\caption{Lawvere theory $\cat{L}$ is based on $\Fop$, from which
it inherits the ``boring'' morphisms that define the products. It adds
the ``interesting'' morphisms that describe the $n$-ary operations (dotted
arrows).}
\centering
\includegraphics[width=0.8\textwidth]{images/lawvere1.png}
\caption{Lawvere theory $\cat{L}$ is based on $\Fop$, from which
it inherits the ``boring'' morphisms that define the products. It adds
the ``interesting'' morphisms that describe the $n$-ary operations (dotted
arrows).}
\end{figure}
Lawvere theories form a category $\cat{Law}$, in which morphisms are
@ -176,8 +176,8 @@ $I$. Given two such theories, $(\cat{L}, I_{\cat{L}})$ and
$(\cat{L'}, I'_{\cat{L'}})$, a morphism between them is a
functor $F \Colon \cat{L} \to \cat{L'}$ such that:
\begin{gather*}
F\ (m \times n) = F\ m \times F\ n \\
F \circ I_{\cat{L}} = I'_{\cat{L'}}
F\ (m \times n) = F\ m \times F\ n \\
F \circ I_{\cat{L}} = I'_{\cat{L'}}
\end{gather*}
Morphisms between Lawvere theories encapsulate the idea of the
interpretation of one theory inside another. For instance, group
@ -208,11 +208,11 @@ products, we require that such a functor preserve finite products. A
model of $\cat{L}$, also called the algebra over the Lawvere theory
$\cat{L}$, is therefore defined by a functor:
\begin{gather*}
M \Colon \cat{L} \to \Set \\
M\ (a \times b) \cong M\ a \times M\ b
M \Colon \cat{L} \to \Set \\
M\ (a \times b) \cong M\ a \times M\ b
\end{gather*}
Notice that we require the preservation of products only \emph{up to
isomorphism}. This is very important, because strict preservation of
isomorphism}. This is very important, because strict preservation of
products would eliminate most interesting theories.
The preservation of products by models means that the image of
@ -269,7 +269,7 @@ structure of monoids. It is a single theory that distills the structure
of all possible monoids, in the sense that the models of this theory
span the whole category $\cat{Mon}$ of monoids. We've already seen a
\hyperref[free-monoids]{universal
construction}, which showed that every monoid can be obtained from an
construction}, which showed that every monoid can be obtained from an
appropriate free monoid by identifying a subset of morphisms. So a
single free monoid already generalizes a whole lot of monoids. There
are, however, infinitely many free monoids. The Lawvere theory for
@ -320,7 +320,7 @@ $\cat{Mon}$.
As you may remember, algebraic theories can be described using monads
--- in particular
\hyperref[algebras-for-monads]{algebras
for monads}. It should be no surprise then that there is a connection
for monads}. It should be no surprise then that there is a connection
between Lawvere theories and monads.
First, let's see how a Lawvere theory induces a monad. It does it
@ -366,7 +366,7 @@ a monad.
It turns out that the category of
\hyperref[algebras-for-monads]{algebras
for this monad} is equivalent to the category of models.
for this monad} is equivalent to the category of models.
You may recall that monad algebras define ways to evaluate expressions
that are formed using monads. A Lawvere theory defines n-ary operations
@ -428,8 +428,8 @@ The lifting simply selects $m$ elements from a tuple of $n$ elements\\
$(a_1, a_2,...a_n)$ (possibly with repetitions).
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/liftpower.png}
\centering
\includegraphics[width=0.5\textwidth]{images/liftpower.png}
\end{figure}
\noindent
@ -462,11 +462,11 @@ morphism with $\cat{L}(m, 1)$ gives us a subset of
$\cat{L}(n, 1)$.
\begin{figure}[H]
\centering
\begin{tikzcd}[column sep=large]
\cat{L}(m, 1) \arrow[r] & \cat{L}(n, 1)\\
{}^m \bullet \arrow[r, "f"'] & \bullet^n
\end{tikzcd}
\centering
\begin{tikzcd}[column sep=large]
\cat{L}(m, 1) \arrow[r] & \cat{L}(n, 1)\\
{}^m \bullet \arrow[r, "f"'] & \bullet^n
\end{tikzcd}
\end{figure}
\noindent
@ -485,24 +485,24 @@ Here, the coend starts as the disjoint sum of sets
$a^n \times \cat{L}(n, 1)$ over all $n$s. The identifications can
be generated by expressing the
\hyperref[ends-and-coends]{coend as
a coequalizer}. We start with an off-diagonal term
a coequalizer}. We start with an off-diagonal term
$a^n \times \cat{L}(m, 1)$. To get to the diagonal, we can apply a
morphism $f \Colon m \to n$ either to the first or
the second component of the product. The two results are then
identified.
\begin{figure}[H]
\centering
\begin{tikzcd}
& a^n \times \cat{L}(m, 1)
\centering
\begin{tikzcd}
& a^n \times \cat{L}(m, 1)
\arrow[dl, "\langle f {,} \id \rangle"']
\arrow[dr, "\langle \id {,} f \rangle"]
& \\
a^m \times \cat{L}(m, 1)
& \scalebox{2.5}[1]{\sim}
a^m \times \cat{L}(m, 1)
& \scalebox{2.5}[1]{\sim}
& a^n \times \cat{L}(n, 1) \\
& f \Colon m \to n &
\end{tikzcd}
\end{tikzcd}
\end{figure}
\noindent
@ -575,17 +575,17 @@ the coend formula, because they can be obtained from:
by lifting $0 \to n$ in two different ways.
\begin{figure}[H]
\centering
\begin{tikzcd}
& a^n \times \cat{L}(0, 1)
\centering
\begin{tikzcd}
& a^n \times \cat{L}(0, 1)
\arrow[dl, "\langle f {,} \id \rangle"']
\arrow[dr, "\langle \id {,} f \rangle"]
& \\
a^0 \times \cat{L}(0, 1)
& \scalebox{2.5}[1]{\sim}
a^0 \times \cat{L}(0, 1)
& \scalebox{2.5}[1]{\sim}
& a^n \times \cat{L}(n, 1) \\
& f \Colon 0 \to n &
\end{tikzcd}
\end{tikzcd}
\end{figure}
\noindent
@ -603,29 +603,29 @@ not their handling.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Enumerate all morphisms between $2$ and $3$ in $\cat{F}$ (the skeleton of
$\cat{FinSet}$).
\item
Show that the category of models for the Lawvere theory of monoids is
equivalent to the category of monad algebras for the list monad.
\item
The Lawvere theory of monoids generates the list monad. Show that its
binary operations can be generated using the corresponding Kleisli
arrows.
\item
\textbf{FinSet} is a subcategory of $\Set$ and there is a
functor that embeds it in $\Set$. Any functor on $\Set$
can be restricted to $\cat{FinSet}$. Show that a finitary functor is
the left Kan extension of its own restriction.
\tightlist
\item
Enumerate all morphisms between $2$ and $3$ in $\cat{F}$ (the skeleton of
$\cat{FinSet}$).
\item
Show that the category of models for the Lawvere theory of monoids is
equivalent to the category of monad algebras for the list monad.
\item
The Lawvere theory of monoids generates the list monad. Show that its
binary operations can be generated using the corresponding Kleisli
arrows.
\item
\textbf{FinSet} is a subcategory of $\Set$ and there is a
functor that embeds it in $\Set$. Any functor on $\Set$
can be restricted to $\cat{FinSet}$. Show that a finitary functor is
the left Kan extension of its own restriction.
\end{enumerate}
\section{Further Reading}
\begin{enumerate}
\tightlist
\item
\urlref{http://www.tac.mta.ca/tac/reprints/articles/5/tr5.pdf}{Functorial Semantics of Algebraic Theories}, F. William Lawvere
\urlref{http://www.tac.mta.ca/tac/reprints/articles/5/tr5.pdf}{Functorial Semantics of Algebraic Theories}, F. William Lawvere
\item
\urlref{http://homepages.inf.ed.ac.uk/gdp/publications/Comp_Eff_Monads.pdf}{Notions of computation determine monads}, Gordon Plotkin and John Power
\urlref{http://homepages.inf.ed.ac.uk/gdp/publications/Comp_Eff_Monads.pdf}{Notions of computation determine monads}, Gordon Plotkin and John Power
\end{enumerate}

View File

@ -47,9 +47,9 @@ are called $0$-cells, morphisms are $1$-cells, and morphisms between
morphisms are $2$-cells.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/twocat.png}
\caption{$0$-cells $a, b$; $1$-cells $f, g$; and a $2$-cell $\alpha$.}
\centering
\includegraphics[width=0.35\textwidth]{images/twocat.png}
\caption{$0$-cells $a, b$; $1$-cells $f, g$; and a $2$-cell $\alpha$.}
\end{figure}
\noindent
@ -99,10 +99,10 @@ words, there is a $2$-cell:
that has an inverse.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/bicat.png}
\caption{Identity law in a bicategory holds up to isomorphism (an invertible
$2$-cell $\rho$).}
\centering
\includegraphics[width=0.35\textwidth]{images/bicat.png}
\caption{Identity law in a bicategory holds up to isomorphism (an invertible
$2$-cell $\rho$).}
\end{figure}
\noindent
@ -117,13 +117,13 @@ An interesting example of a bicategory is the category of spans. A span
between two objects $a$ and $b$ is an object $x$
and a pair of morphisms:
\begin{gather*}
f \Colon x \to a \\
g \Colon x \to b
f \Colon x \to a \\
g \Colon x \to b
\end{gather*}
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{images/span.png}
\centering
\includegraphics[width=0.35\textwidth]{images/span.png}
\end{figure}
\noindent
@ -132,13 +132,13 @@ product. Here, we want to look at spans as $1$-cells in a bicategory. The
first step is to define a composition of spans. Suppose that we have an
adjoining span:
\begin{gather*}
f' \Colon y \to b \\
g' \Colon y \to c
f' \Colon y \to b \\
g' \Colon y \to c
\end{gather*}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/compspan.png}
\centering
\includegraphics[width=0.5\textwidth]{images/compspan.png}
\end{figure}
\noindent
@ -147,16 +147,16 @@ most natural choice for it is the pullback of $g$ along
$f'$. Remember that a pullback is the object $z$
together with two morphisms:
\begin{align*}
h &\Colon z \to x \\
h' &\Colon z \to y
h & \Colon z \to x \\
h' & \Colon z \to y
\end{align*}
such that:
\[g \circ h = f' \circ h'\]
which is universal among all such objects.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/pullspan.png}
\centering
\includegraphics[width=0.5\textwidth]{images/pullspan.png}
\end{figure}
\noindent
@ -169,9 +169,9 @@ a morphism $h$ between their apices, such that the appropriate
triangles commute.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/morphspan.png}
\caption{A $2$-cell in $\cat{Span}$.}
\centering
\includegraphics[width=0.4\textwidth]{images/morphspan.png}
\caption{A $2$-cell in $\cat{Span}$.}
\end{figure}
\noindent
@ -206,8 +206,8 @@ we get:
\[\mu \Colon T \circ T \to T\]
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/monad.png}
\centering
\includegraphics[width=0.3\textwidth]{images/monad.png}
\end{figure}
\noindent
@ -221,14 +221,14 @@ As we've seen earlier, the hom-category $\cat{C}(a, a)$ is a monoidal
category. We can therefore define a monoid in $\cat{C}(a, a)$ by
picking a $1$-cell, $T$, and two $2$-cells:
\begin{align*}
\eta &\Colon I \to T \\
\mu &\Colon T \circ T \to T
\eta & \Colon I \to T \\
\mu & \Colon T \circ T \to T
\end{align*}
satisfying the monoid laws. We call \emph{this} a monad.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/bimonad.png}
\centering
\includegraphics[width=0.3\textwidth]{images/bimonad.png}
\end{figure}
\noindent
@ -243,13 +243,13 @@ $Ob$. Next, we pick an endo-$1$-cell: a span from $Ob$ back
to $Ob$. It has a set at the apex, which I will call $Ar$,
equipped with two functions:
\begin{align*}
dom &\Colon Ar \to Ob \\
cod &\Colon Ar \to Ob
dom & \Colon Ar \to Ob \\
cod & \Colon Ar \to Ob
\end{align*}
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/spanmonad.png}
\centering
\includegraphics[width=0.3\textwidth]{images/spanmonad.png}
\end{figure}
\noindent
@ -266,13 +266,13 @@ $Ob$ and $Ar$. In other words, $\eta$ assigns an
``arrow'' to every ``object.'' A $2$-cell in $\cat{Span}$ must satisfy
commutation conditions --- in this case:
\begin{align*}
dom &\circ \eta = \id \\
cod &\circ \eta = \id
dom & \circ \eta = \id \\
cod & \circ \eta = \id
\end{align*}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/spanunit.png}
\centering
\includegraphics[width=0.4\textwidth]{images/spanunit.png}
\end{figure}
\noindent
@ -292,8 +292,8 @@ We say that $a_1$ and $a_2$ are ``composable,'' because the
domain of one is the codomain of the other.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/spanmul.png}
\centering
\includegraphics[width=0.5\textwidth]{images/spanmul.png}
\end{figure}
\noindent
@ -319,22 +319,22 @@ all of mathematics, this is a very humbling realization.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Derive unit and associativity laws for the tensor product defined as
composition of endo-$1$-cells in a bicategory.
\item
Check that monad laws for a monad in $\cat{Span}$ correspond to
identity and associativity laws in the resulting category.
\item
Show that a monad in $\cat{Prof}$ is an identity-on-objects functor.
\item
What's a monad algebra for a monad in $\cat{Span}$?
\tightlist
\item
Derive unit and associativity laws for the tensor product defined as
composition of endo-$1$-cells in a bicategory.
\item
Check that monad laws for a monad in $\cat{Span}$ correspond to
identity and associativity laws in the resulting category.
\item
Show that a monad in $\cat{Prof}$ is an identity-on-objects functor.
\item
What's a monad algebra for a monad in $\cat{Span}$?
\end{enumerate}
\section{Bibliography}
\begin{enumerate}
\tightlist
\item
\urlref{https://graphicallinearalgebra.net/2017/04/16/a-monoid-is-a-category-a-category-is-a-monad-a-monad-is-a-monoid/}{Paweł Sobocińskis blog}.
\urlref{https://graphicallinearalgebra.net/2017/04/16/a-monoid-is-a-category-a-category-is-a-monad-a-monad-is-a-monoid/}{Paweł Sobocińskis blog}.
\end{enumerate}

View File

@ -36,8 +36,8 @@ $L \circ R$; and two possible identity functors: one in $\cat{C}$
and another in $\cat{D}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-1.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-1.jpg}
\end{figure}
\noindent
@ -78,20 +78,20 @@ between $L \circ R$ and the identity functor $I_{\cat{C}}$.
Adjunction is even weaker than equivalence, because it doesn't require
that the composition of the two functors be \emph{isomorphic} to the
identity functor. Instead it stipulates the existence of a \newterm{one
way} natural transformation from $I_{\cat{D}}$ to $R \circ L$, and
way} natural transformation from $I_{\cat{D}}$ to $R \circ L$, and
another from $L \circ R$ to $I_{\cat{C}}$. Here are the signatures of
these two natural transformations:
\begin{gather*}
\eta \Colon I_{\cat{D}} \to R \circ L \\
\varepsilon \Colon L \circ R \to I_{\cat{C}}
\eta \Colon I_{\cat{D}} \to R \circ L \\
\varepsilon \Colon L \circ R \to I_{\cat{C}}
\end{gather*}
$\eta$ is called the unit, and $\varepsilon$ the counit of the adjunction.
Notice the asymmetry between these two definitions. In general, we don't
have the two remaining mappings:
\begin{gather*}
R \circ L \to I_{\cat{D}} \quad\quad\text{not necessarily} \\
I_{\cat{C}} \to L \circ R \quad\quad\text{not necessarily}
R \circ L \to I_{\cat{D}} \quad\quad\text{not necessarily} \\
I_{\cat{C}} \to L \circ R \quad\quad\text{not necessarily}
\end{gather*}
Because of this asymmetry, the functor $L$ is called the
\newterm{left adjoint} to the functor $R$, while the functor
@ -104,8 +104,8 @@ To better understand the adjunction, let's analyze the unit and the
counit in more detail.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-unit.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-unit.jpg}
\end{figure}
\noindent
@ -123,8 +123,8 @@ $R \circ L$ to pick our target object $d'$. Then we
shoot an arrow --- the morphism $\eta_d$ --- to our target.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-counit.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-counit.jpg}
\end{figure}
\noindent
@ -144,8 +144,8 @@ identity on $\cat{C}$. That leads to some ``obvious'' consistency
conditions, which make sure that introduction followed by elimination
doesn't change anything:
\begin{gather*}
L = L \circ I_{\cat{D}} \to L \circ R \circ L \to I_{\cat{C}} \circ L = L \\
R = I_{\cat{D}} \circ R \to R \circ L \circ R \to R \circ I_{\cat{C}} = R
L = L \circ I_{\cat{D}} \to L \circ R \circ L \to I_{\cat{C}} \circ L = L \\
R = I_{\cat{D}} \circ R \to R \circ L \circ R \to R \circ I_{\cat{C}} = R
\end{gather*}
These are called triangular identities because they make the following
diagrams commute:
@ -156,9 +156,9 @@ diagrams commute:
\begin{subfigure}
\centering
\begin{tikzcd}[column sep=large, row sep=large]
L \arrow[rd, equal] \arrow[r, "L \circ \eta"]
& L \circ R \circ L \arrow[d, "\epsilon \circ L"] \\
& L
L \arrow[rd, equal] \arrow[r, "L \circ \eta"]
& L \circ R \circ L \arrow[d, "\epsilon \circ L"] \\
& L
\end{tikzcd}
\end{subfigure}%
\hspace{1cm}
@ -166,8 +166,8 @@ diagrams commute:
\centering
\begin{tikzcd}[column sep=large, row sep=large]
R \arrow[rd, equal] \arrow[r, "\eta \circ R"]
& R \circ L \circ R \arrow[d, "R \circ \epsilon"] \\
& R
& R \circ L \circ R \arrow[d, "R \circ \epsilon"] \\
& R
\end{tikzcd}
\end{subfigure}
\end{figure}
@ -177,8 +177,8 @@ These are diagrams in the functor category: the arrows are natural
transformations, and their composition is the horizontal composition of
natural transformations. In components, these identities become:
\begin{gather*}
\varepsilon_{L d} \circ L \eta_d = \id_{L d} \\
R \varepsilon_{c} \circ \eta_{R c} = \id_{R c}
\varepsilon_{L d} \circ L \eta_d = \id_{L d} \\
R \varepsilon_{c} \circ \eta_{R c} = \id_{R c}
\end{gather*}
We often see unit and counit in Haskell under different names. Unit is
known as \code{return} (or \code{pure}, in the definition of
@ -254,8 +254,8 @@ objects exists in a category, it can be also defined through an
adjunction.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-homsets.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-homsets.jpg}
\end{figure}
\noindent
@ -281,14 +281,14 @@ precisely, we have a natural transformation $\varphi$ between the
following two (covariant) functors from $\cat{C}$ to $\Set$. Here's
the action of these functors on objects:
\begin{gather*}
c \to \cat{C}(L d, c) \\
c \to \cat{D}(d, R c)
c \to \cat{C}(L d, c) \\
c \to \cat{D}(d, R c)
\end{gather*}
The other natural transformation, $\psi$, acts between the following
(contravariant) functors:
\begin{gather*}
d \to \cat{C}(L d, c) \\
d \to \cat{D}(d, R c)
d \to \cat{C}(L d, c) \\
d \to \cat{D}(d, R c)
\end{gather*}
Both natural transformations must be invertible.
@ -345,7 +345,7 @@ as an exercise.
We are now ready to explain why, in Haskell, the right adjoint is
automatically a \hyperref[representable-functors]{representable
functor}. The reason for this is that, to the first approximation, we
functor}. The reason for this is that, to the first approximation, we
can treat the category of Haskell types as the category of sets.
When the right category $\cat{D}$ is $\Set$, the right adjoint
@ -373,7 +373,7 @@ We have previously introduced several concepts using universal
constructions. Many of those concepts, when defined globally, are easier
to express using adjunctions. The simplest non-trivial example is that
of the product. The gist of the \hyperref[products-and-coproducts]{universal
construction of the product} is the ability to factorize any
construction of the product} is the ability to factorize any
product-like candidate through the universal product.
More precisely, the product of two objects $a$ and $b$ is
@ -411,8 +411,8 @@ product category $\cat{C}\times{}\cat{C}$. Pairs of morphism from $\cat{C}$ are
morphisms in the product category $\cat{C}\times{}\cat{C}$.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-productcat.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-productcat.jpg}
\end{figure}
\noindent
@ -439,8 +439,8 @@ first hom-set is in the product category $\cat{C}\times{}\cat{C}$, and the secon
in $\cat{C}$. A general morphism in $\cat{C}\times{}\cat{C}$ would be a pair of
morphisms $\langle f, g \rangle$:
\begin{gather*}
f \Colon c' \to a \\
g \Colon c'' \to b
f \Colon c' \to a \\
g \Colon c'' \to b
\end{gather*}
with $c''$ potentially different from
$c'$. But to define a product, we are interested in a
@ -466,8 +466,8 @@ $a\times{}b$. We recognize this element of the hom-set as the
\[\ldots{} \to (c \to (a, b))\]
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/adj-product.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/adj-product.jpg}
\end{figure}
\noindent
@ -517,13 +517,13 @@ for instance:
The exponential $b^a$, or the function object $a \Rightarrow b$, can be
defined using a \hyperref[function-types]{universal
construction}. This construction, if it exists for all pairs of objects,
construction}. This construction, if it exists for all pairs of objects,
can be seen as an adjunction. Again, the trick is to concentrate on the
statement:
\begin{quote}
For any other object $z$ with a morphism $g \Colon z\times{}a \to b$
there is a unique morphism $h \Colon z \to (a \Rightarrow b)$
For any other object $z$ with a morphism $g \Colon z\times{}a \to b$
there is a unique morphism $h \Colon z \to (a \Rightarrow b)$
\end{quote}
This statement establishes a mapping between hom-sets.
@ -541,13 +541,13 @@ The mapping of hom-sets that underlies this adjunction is best seen by
redrawing the diagram that we used in the universal construction.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/adj-expo.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/adj-expo.jpg}
\end{figure}
\noindent
Notice that the $eval$ morphism\footnote{See ch.9 on \hyperref[function-types]{universal
construction}.} is nothing else but the counit of
construction}.} is nothing else but the counit of
this adjunction:
\[(a \Rightarrow b)\times{}a \to b\]
where:
@ -560,26 +560,26 @@ a functor has an adjoint, this adjoint is unique up to isomorphism.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Derive the naturality square for $\psi$, the transformation
between the two (contravariant) functors:
\begin{gather*}
a \to \cat{C}(L a, b) \\
a \to \cat{D}(a, R b)
\end{gather*}
\item
Derive the counit $\varepsilon$ starting from the hom-sets isomorphism in
the second definition of the adjunction.
\item
Complete the proof of equivalence of the two definitions of the
adjunction.
\item
Show that the coproduct can be defined by an adjunction. Start with
the definition of the factorizer for a coproduct.
\item
Show that the coproduct is the left adjoint of the diagonal functor.
\item
Define the adjunction between a product and a function object in
Haskell.
\tightlist
\item
Derive the naturality square for $\psi$, the transformation
between the two (contravariant) functors:
\begin{gather*}
a \to \cat{C}(L a, b) \\
a \to \cat{D}(a, R b)
\end{gather*}
\item
Derive the counit $\varepsilon$ starting from the hom-sets isomorphism in
the second definition of the adjunction.
\item
Complete the proof of equivalence of the two definitions of the
adjunction.
\item
Show that the coproduct can be defined by an adjunction. Start with
the definition of the factorizer for a coproduct.
\item
Show that the coproduct is the left adjoint of the diagonal functor.
\item
Define the adjunction between a product and a function object in
Haskell.
\end{enumerate}

View File

@ -2,7 +2,7 @@
\lettrine[lhang=0.17]{F}{ree constructions are} a powerful application of adjunctions. A
\newterm{free functor} is defined as the left adjoint to a \newterm{forgetful
functor}. A forgetful functor is usually a pretty simple functor that
functor}. A forgetful functor is usually a pretty simple functor that
forgets some structure. For instance, lots of interesting categories are
built on top of sets. But categorical objects, which abstract those
sets, have no internal structure --- they have no elements. Still, those
@ -27,12 +27,12 @@ morphism in $\cat{Mon}$.\\
Things to keep in mind:
\begin{itemize}
\tightlist
\item
There may be many monoids that map to the same set, and
\item
There are fewer (or at most as many as) monoid morphisms than there
are functions between their underlying sets.
\tightlist
\item
There may be many monoids that map to the same set, and
\item
There are fewer (or at most as many as) monoid morphisms than there
are functions between their underlying sets.
\end{itemize}
\noindent
@ -40,15 +40,15 @@ The functor $F$ that's the left adjoint to the forgetful functor
$U$ is the free functor that builds free monoids from their
generator sets. The adjunction follows from the free monoid
universal construction we've discussed before.\footnote{See ch.13 on
\hyperref[free-monoids]{free monoids}.}
\hyperref[free-monoids]{free monoids}.}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{images/forgetful.jpg}
\caption{Monoids $m_1$ and $m_2$ have the same
underlying set. There are more functions between the underlying sets of
$m_2$ and $m_3$ than there are morphisms
between them.}
\centering
\includegraphics[width=0.6\textwidth]{images/forgetful.jpg}
\caption{Monoids $m_1$ and $m_2$ have the same
underlying set. There are more functions between the underlying sets of
$m_2$ and $m_3$ than there are morphisms
between them.}
\end{figure}
\noindent
@ -57,23 +57,23 @@ In terms of hom-sets, we can write this adjunction as:
This (natural in $x$ and $m$) isomorphism tells us that:
\begin{itemize}
\tightlist
\item
For every monoid homomorphism between the free monoid $F x$
generated by $x$ and an arbitrary monoid $m$ there is a
unique function that embeds the set of generators $x$ in the
underlying set of $m$. It's a function in
$\Set(x, U m)$.
\item
For every function that embeds $x$ in the underlying set of
some $m$ there is a unique monoid morphism between the free
monoid generated by $x$ and the monoid $m$. (This is the
morphism we called $h$ in our universal construction.)
\tightlist
\item
For every monoid homomorphism between the free monoid $F x$
generated by $x$ and an arbitrary monoid $m$ there is a
unique function that embeds the set of generators $x$ in the
underlying set of $m$. It's a function in
$\Set(x, U m)$.
\item
For every function that embeds $x$ in the underlying set of
some $m$ there is a unique monoid morphism between the free
monoid generated by $x$ and the monoid $m$. (This is the
morphism we called $h$ in our universal construction.)
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{images/freemonadjunction.jpg}
\centering
\includegraphics[width=0.8\textwidth]{images/freemonadjunction.jpg}
\end{figure}
\noindent
@ -90,7 +90,7 @@ versa.
In Haskell, the list data structure is a free monoid (with some caveats:
see \urlref{http://comonad.com/reader/2015/free-monoids-in-haskell/}{Dan
Doel's blog post}). A list type \code{{[}a{]}} is a free monoid with
Doel's blog post}). A list type \code{{[}a{]}} is a free monoid with
the type \code{a} representing the set of generators. For instance,
the type \code{{[}Char{]}} contains the unit element --- the empty
list \code{{[}{]}} --- and the singletons like
@ -174,8 +174,8 @@ $\cat{C}(c', c)$ have to preserve the additional structure,
whereas the ones in $\cat{D}(U c', U c)$ don't.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{images/forgettingmorphisms.jpg}
\centering
\includegraphics[width=0.45\textwidth]{images/forgettingmorphisms.jpg}
\end{figure}
\noindent
@ -195,8 +195,8 @@ preserve by morphisms). Such ``structure-free'' objects are called free
objects.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\textwidth]{images/freeimage.jpg}
\centering
\includegraphics[width=0.45\textwidth]{images/freeimage.jpg}
\end{figure}
\noindent
@ -209,7 +209,7 @@ there is no identification of ${[}2, 3{]}$ and $6$, a morphism from this
free monoid to any other monoid $m$ is allowed to map them
separately. But it's also okay for it to map both ${[}2, 3{]}$ and $6$
(their product) to the same element of $m$. Or to identify ${[}2,
3{]}$ and $5$ (their sum) in an additive monoid, and so on. Different
3{]}$ and $5$ (their sum) in an additive monoid, and so on. Different
identifications give you different monoids.
This leads to another interesting intuition: Free monoids, instead of
@ -234,10 +234,10 @@ intermediate results.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Consider a free monoid built from a singleton set as its generator.
Show that there is a one-to-one correspondence between morphisms from
this free monoid to any monoid $m$, and functions from the
singleton set to the underlying set of $m$.
\tightlist
\item
Consider a free monoid built from a singleton set as its generator.
Show that there is a one-to-one correspondence between morphisms from
this free monoid to any monoid $m$, and functions from the
singleton set to the underlying set of $m$.
\end{enumerate}

View File

@ -21,19 +21,19 @@ tape) and its applications. Here's a little sample of things that you
can do with it:
\begin{itemize}
\tightlist
\item
sealing ducts
\item
fixing CO\textsubscript{2} scrubbers on board Apollo 13
\item
wart treatment
\item
fixing Apple's iPhone 4 dropped call issue
\item
making a prom dress
\item
building a suspension bridge
\tightlist
\item
sealing ducts
\item
fixing CO\textsubscript{2} scrubbers on board Apollo 13
\item
wart treatment
\item
fixing Apple's iPhone 4 dropped call issue
\item
making a prom dress
\item
building a suspension bridge
\end{itemize}
\noindent
@ -83,7 +83,7 @@ the first place.
We have previously arrived at the
\hyperref[kleisli-categories]{writer
monad} by embellishing regular functions. The particular embellishment
monad} by embellishing regular functions. The particular embellishment
was done by pairing their return values with strings or, more generally,
with elements of a monoid. We can now recognize that such an embellishment
is a functor:
@ -311,7 +311,7 @@ Interestingly, the equivalent of the \code{do} notation has found its
application in imperative languages, C++ in particular. I'm talking
about resumable functions or coroutines. It's not a secret that C++
\urlref{https://bartoszmilewski.com/2014/02/26/c17-i-see-a-monad-in-your-future/}{futures
form a monad}. It's an example of the continuation monad, which we'll
form a monad}. It's an example of the continuation monad, which we'll
discuss shortly. The problem with continuations is that they are very
hard to compose. In Haskell, we use the \code{do} notation to turn the
spaghetti of ``my handler will call your handler'' into something that
@ -319,7 +319,7 @@ looks very much like sequential code. Resumable functions make the same
transformation possible in C++. And the same mechanism can be applied to
turn the
\urlref{https://bartoszmilewski.com/2014/04/21/getting-lazy-with-c/}{spaghetti
of nested loops} into list comprehensions or ``generators,'' which are
of nested loops} into list comprehensions or ``generators,'' which are
essentially the \code{do} notation for the list monad. Without the
unifying abstraction of the monad, each of these problems is typically
addressed by providing custom extensions to the language. In Haskell,

View File

@ -13,36 +13,36 @@ functions.
Here is a short list of similar problems, copied from
\urlref{https://core.ac.uk/download/pdf/21173011.pdf}{Eugenio Moggi's
seminal paper}, all of which are traditionally solved by abandoning the
seminal paper}, all of which are traditionally solved by abandoning the
purity of functions.
\begin{itemize}
\tightlist
\item
Partiality: Computations that may not terminate
\item
Nondeterminism: Computations that may return many results
\item
Side effects: Computations that access/modify state
\begin{itemize}
\tightlist
\item
Read-only state, or the environment
Partiality: Computations that may not terminate
\item
Write-only state, or a log
Nondeterminism: Computations that may return many results
\item
Read/write state
\end{itemize}
\item
Exceptions: Partial functions that may fail
\item
Continuations: Ability to save state of the program and then restore
it on demand
\item
Interactive Input
\item
Interactive Output
Side effects: Computations that access/modify state
\begin{itemize}
\tightlist
\item
Read-only state, or the environment
\item
Write-only state, or a log
\item
Read/write state
\end{itemize}
\item
Exceptions: Partial functions that may fail
\item
Continuations: Ability to save state of the program and then restore
it on demand
\item
Interactive Input
\item
Interactive Output
\end{itemize}
What really is mind blowing is that all these problems may be solved
@ -102,7 +102,7 @@ Haskell (lifted) types and functions rather than the simpler
$\Set$. It is not clear, though, that $\Hask$ is a real
category (see this
\urlref{http://math.andrej.com/2016/08/06/hask-is-not-a-category/}{Andrej
Bauer post}).
Bauer post}).
\subsection{Nondeterminism}
@ -134,7 +134,7 @@ From the programmer's point of view, working with a list is easier than,
for instance, calling a non-deterministic function in a loop, or
implementing a function that returns an iterator (although,
\urlref{http://ericniebler.com/2014/04/27/range-comprehensions/}{in modern
C++}, returning a lazy range would be almost equivalent to returning a
C++}, returning a lazy range would be almost equivalent to returning a
list in Haskell).
A good example of using non-determinism creatively is in game

View File

@ -15,8 +15,8 @@ like $1$ or $2$, bound together with operators like plus or times. As
programmers, we often think of expressions as trees.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/exptree.png}
\centering
\includegraphics[width=0.3\textwidth]{images/exptree.png}
\end{figure}
\noindent
@ -79,8 +79,8 @@ implemented using $\mu$:
\[g \circ_T f = \mu_c \circ (T\ g) \circ f\]
where
\begin{gather*}
f \Colon a \to T\ b \\
g \Colon b \to T\ c
f \Colon a \to T\ b \\
g \Colon b \to T\ c
\end{gather*}
Here $T$, being a functor, can be applied to the morphism
$g$. It might be easier to recognize this formula in Haskell
@ -114,8 +114,8 @@ horizontal composition of two natural transformations:
\[I_T \circ \mu\]
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/assoc1.png}
\centering
\includegraphics[width=0.4\textwidth]{images/assoc1.png}
\end{figure}
\noindent
@ -131,8 +131,8 @@ must mean $I_T$ in this context.
We can also draw the diagram in the (endo-) functor category ${[}\cat{C}, \cat{C}{]}$:
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/assoc2.png}
\centering
\includegraphics[width=0.3\textwidth]{images/assoc2.png}
\end{figure}
\noindent
@ -142,8 +142,8 @@ $T \circ T$ which, again, can be reduced to $T$ using $\mu$. We
require that the two paths produce the same result.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/assoc.png}
\centering
\includegraphics[width=0.3\textwidth]{images/assoc.png}
\end{figure}
\noindent
@ -155,8 +155,8 @@ transformation directly to \code{T}. And, by analogy, the same should
be true for $T \circ \eta$.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/unitlawcomp-1.png}
\centering
\includegraphics[width=0.4\textwidth]{images/unitlawcomp-1.png}
\end{figure}
\noindent
@ -275,8 +275,8 @@ up to isomorphism. The associator and the two unitors are natural
isomorphisms. The laws can be represented by commuting diagrams.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/assocmon.png}
\centering
\includegraphics[width=0.5\textwidth]{images/assocmon.png}
\end{figure}
\noindent
@ -312,9 +312,9 @@ and a distinct object $i$ called the unit object, together with
three natural isomorphisms called, respectively, the associator and the
left and right unitors:
\begin{align*}
\alpha_{a b c} &\Colon (a \otimes b) \otimes c \to a \otimes (b \otimes c) \\
\lambda_a &\Colon i \otimes a \to a \\
\rho_a &\Colon a \otimes i \to a
\alpha_{a b c} & \Colon (a \otimes b) \otimes c \to a \otimes (b \otimes c) \\
\lambda_a & \Colon i \otimes a \to a \\
\rho_a & \Colon a \otimes i \to a
\end{align*}
(There is also a coherence condition for simplifying a quadruple tensor
product.)
@ -335,14 +335,14 @@ of $m$, but they are isomorphic through the associator. Similarly
for higher powers of $m$ (that's where we need the coherence
conditions). To form a monoid we need to pick two morphisms:
\begin{align*}
\mu &\Colon m \otimes m \to m \\
\eta &\Colon i \to m
\mu & \Colon m \otimes m \to m \\
\eta & \Colon i \to m
\end{align*}
where $i$ is the unit object for our tensor product.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-1.jpg}
\centering
\includegraphics[width=0.4\textwidth]{images/monoid-1.jpg}
\end{figure}
\noindent
@ -350,13 +350,13 @@ These morphisms have to satisfy associativity and unit laws, which can
be expressed in terms of the following commuting diagrams:
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/assoctensor.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/assoctensor.jpg}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/unitmon.jpg}
\centering
\includegraphics[width=0.5\textwidth]{images/unitmon.jpg}
\end{figure}
\noindent
@ -395,8 +395,8 @@ transformations, and tensor products by composition, you get:
which you may recognize as the special case of horizontal composition.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/horizcomp.png}
\centering
\includegraphics[width=0.4\textwidth]{images/horizcomp.png}
\end{figure}
\noindent
@ -411,19 +411,19 @@ What's a monoid in this category? It's an object --- that is an
endofunctor $T$; and two morphisms --- that is natural
transformations:
\begin{gather*}
\mu \Colon T \circ T \to T \\
\eta \Colon I \to T
\mu \Colon T \circ T \to T \\
\eta \Colon I \to T
\end{gather*}
Not only that, here are the monoid laws:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/assoc.png}
\centering
\includegraphics[width=0.4\textwidth]{images/assoc.png}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{images/unitlawcomp.png}
\centering
\includegraphics[width=0.5\textwidth]{images/unitlawcomp.png}
\end{figure}
\noindent
@ -431,7 +431,7 @@ They are exactly the monad laws we've seen before. Now you understand
the famous quote from Saunders Mac Lane:
\begin{quote}
All told, monad is just a monoid in the category of endofunctors.
All told, monad is just a monoid in the category of endofunctors.
\end{quote}
You might have seen it emblazoned on some t-shirts at functional
programming conferences.
@ -445,8 +445,8 @@ giving rise to two endofunctors, $R \circ L$ and $L \circ R$.
As per an adjunction, these endofunctors are related to identity
functors through two natural transformations called unit and counit:
\begin{gather*}
\eta \Colon I_{\cat{D}} \to R \circ L \\
\varepsilon \Colon L \circ R \to I_{\cat{C}}
\eta \Colon I_{\cat{D}} \to R \circ L \\
\varepsilon \Colon L \circ R \to I_{\cat{C}}
\end{gather*}
Immediately we see that the unit of an adjunction looks just like the
unit of a monad. It turns out that the endofunctor $R \circ L$ is
@ -467,8 +467,8 @@ because an adjunction usually involves two categories. However, the
definitions of an exponential, or a function object, is an exception.
Here are the two endofunctors that form this adjunction:
\begin{gather*}
L\ z = z\times{}s \\
R\ b = s \Rightarrow b
L\ z = z\times{}s \\
R\ b = s \Rightarrow b
\end{gather*}
You may recognize their composition as the familiar state monad:
\[R\ (L\ z) = s \Rightarrow (z\times{}s)\]

View File

@ -226,8 +226,8 @@ duality. As with the monad, we start with an endofunctor \code{T}. The
two natural transformations, $\eta$ and $\mu$, that define the monad are simply
reversed for the comonad:
\begin{align*}
\varepsilon &\Colon T \to I \\
\delta &\Colon T \to T^2
\varepsilon & \Colon T \to I \\
\delta & \Colon T \to T^2
\end{align*}
The components of these transformations correspond to \code{extract}
and \code{duplicate}. Comonad laws are the mirror image of monad laws.
@ -255,14 +255,14 @@ approach to a monad, we used a more general definition of a monoid as an
object in a monoidal category. The construction was based on two
morphisms:
\begin{align*}
\mu &\Colon m \otimes m \to m \\
\eta &\Colon i \to m
\mu & \Colon m \otimes m \to m \\
\eta & \Colon i \to m
\end{align*}
The reversal of these morphisms produces a comonoid in a monoidal
category:
\begin{align*}
\delta &\Colon m \to m \otimes m \\
\varepsilon &\Colon m \to i
\delta & \Colon m \to m \otimes m \\
\varepsilon & \Colon m \to i
\end{align*}
One can write a definition of a comonoid in Haskell:
@ -280,7 +280,7 @@ Now consider comonoid laws that are dual to the monoid unit laws.
Here, \code{lambda} and \code{rho} are the left and right unitors,
respectively (see the definition of
\hyperref[monads-categorically]{monoidal
categories}). Plugging in the definitions, we get:
categories}). Plugging in the definitions, we get:
\src{snippet29}
which proves that \code{g = id}. Similarly, the second law expands
@ -296,7 +296,7 @@ And it turns out that, just like the monad is a monoid in the category
of endofunctors,
\begin{quote}
The comonad is a comonoid in the category of endofunctors.
The comonad is a comonoid in the category of endofunctors.
\end{quote}
\section{The Store Comonad}
@ -307,8 +307,8 @@ It's called the costate comonad or, alternatively, the store comonad.
We've seen before that the state monad is generated by the adjunction
that defines the exponentials:
\begin{align*}
L\ z &= z\times{}s \\
R\ a &= s \Rightarrow a
L\ z & = z\times{}s \\
R\ a & = s \Rightarrow a
\end{align*}
We'll use the same adjunction to define the costate comonad. A comonad
is defined by the composition $L \circ R$:
@ -336,8 +336,8 @@ can be rewritten as partially applied data constructor:
\src{snippet35}
We construct $\delta$, or \code{duplicate}, as the horizontal composition:
\begin{align*}
\delta &\Colon L \circ R \to L \circ R \circ L \circ R \\
\delta &= L \circ \eta \circ R
\delta & \Colon L \circ R \to L \circ R \circ L \circ R \\
\delta & = L \circ \eta \circ R
\end{align*}
We have to sneak $\eta$ through the leftmost $L$, which is the
\code{Product} functor. It means acting with $\eta$, or \code{Store f}, on
@ -393,8 +393,8 @@ could be implemented to read the value of the \code{s} field from
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Implement the Conway's Game of Life using the \code{Store} comonad.
Hint: What type do you pick for \code{s}?
\tightlist
\item
Implement the Conway's Game of Life using the \code{Store} comonad.
Hint: What type do you pick for \code{s}?
\end{enumerate}

View File

@ -7,8 +7,8 @@ more juice can we squeeze out of this simple concept?
Let's try. Take this definition of a monoid as a set $m$ with a
pair of functions:
\begin{align*}
\mu &\Colon m\times{}m \to m \\
\eta &\Colon 1 \to m
\mu & \Colon m\times{}m \to m \\
\eta & \Colon 1 \to m
\end{align*}
Here, 1 is the terminal object in $\Set$ --- the singleton set.
The first function defines multiplication (it takes a pair of elements
@ -20,8 +20,8 @@ and just consider ``potential monoids.'' A pair of functions is an
element of a Cartesian product of two sets of functions. We know that
these sets may be represented as exponential objects:
\begin{align*}
\mu &\in m^{m\times{}m} \\
\eta &\in m^1
\mu & \in m^{m\times{}m} \\
\eta & \in m^1
\end{align*}
The Cartesian product of these two sets is:
\[m^{m\times{}m}\times{}m^1\]
@ -42,9 +42,9 @@ $m \to m$. As an example, integers form a group with
addition as a binary operation, zero as the unit, and negation as the
inverse. To define a group we would start with a triple of functions:
\begin{align*}
m\times{}m \to m \\
m \to m \\
1 \to m
m\times{}m \to m \\
m \to m \\
1 \to m
\end{align*}
As before, we can combine all these triples into one set of functions:
\[m\times{}m + m + 1 \to m\]
@ -94,7 +94,7 @@ In the monoid example, the functor in question is:
\src{snippet02}
This is Haskell for $1 + a\times{}a$ (remember
\hyperref[simple-algebraic-data-types]{algebraic
data structures}).
data structures}).
A ring would be defined using the following functor:
@ -159,7 +159,7 @@ Of course, this is a hand-waving argument, and I'll make it more
rigorous later.
Applying an endofunctor infinitely many times produces a \newterm{fixed
point}, an object defined as:
point}, an object defined as:
\[Fix\ f = f\ (Fix\ f)\]
The intuition behind this definition is that, since we applied
$f$ infinitely many times to get $Fix\ f$, applying it one
@ -208,8 +208,8 @@ be equal:
\[g \circ F\ m = m \circ f\]
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/alg.png}
\centering
\includegraphics[width=0.3\textwidth]{images/alg.png}
\end{figure}
\noindent
@ -227,8 +227,8 @@ $m$ from it to any other F-algebra. Since $m$ is a
homomorphism, the following diagram must commute:
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/alg2.png}
\centering
\includegraphics[width=0.3\textwidth]{images/alg2.png}
\end{figure}
\noindent
@ -242,8 +242,8 @@ homomorphism $m$ from it to $(F\ i, F\ j)$. The following
diagram must commute:
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/alg3a.png}
\centering
\includegraphics[width=0.3\textwidth]{images/alg3a.png}
\end{figure}
\noindent
@ -251,8 +251,8 @@ But we also have this trivially commuting diagram (both paths are the
same!):
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{images/alg3.png}
\centering
\includegraphics[width=0.3\textwidth]{images/alg3.png}
\end{figure}
\noindent
@ -261,8 +261,8 @@ algebras, mapping $(F\ i, F\ j)$ to $(i, j)$. We can
glue these two diagrams together to get:
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{images/alg4.png}
\centering
\includegraphics[width=0.6\textwidth]{images/alg4.png}
\end{figure}
\noindent
@ -292,8 +292,8 @@ the fixed point does not depend on $a$.
Natural numbers can also be defined as an F-algebra. The starting point
is the pair of morphisms:
\begin{align*}
zero &\Colon 1 \to N \\
succ &\Colon N \to N
zero & \Colon 1 \to N \\
succ & \Colon N \to N
\end{align*}
The first one picks the zero, and the second one maps all numbers to
their successors. As before, we can combine the two into one:
@ -318,8 +318,8 @@ algebra to any other algebra over the same functor. Let's pick an
algebra whose carrier is \code{a} and the evaluator is \code{alg}.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/alg5.png}
\centering
\includegraphics[width=0.4\textwidth]{images/alg5.png}
\end{figure}
\noindent
@ -332,8 +332,8 @@ isomorphism. We called its inverse \code{unFix}. We can therefore flip
one arrow in this diagram to get:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/alg6.png}
\centering
\includegraphics[width=0.4\textwidth]{images/alg6.png}
\end{figure}
\noindent
@ -431,8 +431,8 @@ coalgebra. For every other algebra $(a, f)$ there is a unique
homomorphism $m$ that makes the following diagram commute:
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{images/alg7.png}
\centering
\includegraphics[width=0.4\textwidth]{images/alg7.png}
\end{figure}
\noindent
@ -523,21 +523,21 @@ with the comonad structure. We'll talk about this in the next section.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
Implement the evaluation function for a ring of polynomials of one
variable. You can represent a polynomial as a list of coefficients in
front of powers of $x$. For instance, $4x^2-1$ would be
represented as (starting with the zero'th power)
\code{{[}-1, 0, 4{]}}.
\item
Generalize the previous construction to polynomials of many
independent variables, like $x^2y-3y^3z$.
\item
Implement the algebra for the ring of $2\times{}2$ matrices.
\item
Define a coalgebra whose anamorphism produces a list of squares of
natural numbers.
\item
Use \code{unfoldr} to generate a list of the first $n$ primes.
\tightlist
\item
Implement the evaluation function for a ring of polynomials of one
variable. You can represent a polynomial as a list of coefficients in
front of powers of $x$. For instance, $4x^2-1$ would be
represented as (starting with the zero'th power)
\code{{[}-1, 0, 4{]}}.
\item
Generalize the previous construction to polynomials of many
independent variables, like $x^2y-3y^3z$.
\item
Implement the algebra for the ring of $2\times{}2$ matrices.
\item
Define a coalgebra whose anamorphism produces a list of squares of
natural numbers.
\item
Use \code{unfoldr} to generate a list of the first $n$ primes.
\end{enumerate}

View File

@ -7,14 +7,14 @@ but we can also answer a few interesting questions.
One such question concerns the relation between monads and adjunctions.
As we've seen, every adjunction \hyperref[monads-categorically]{defines
a monad} (and a comonad). The question is: Can every monad (comonad) be
a monad} (and a comonad). The question is: Can every monad (comonad) be
derived from an adjunction? The answer is positive. There is a whole
family of adjunctions that generate a given monad. I'll show you two
such adjunctions.
\begin{figure}[H]
\centering
\includegraphics[width=0.25\textwidth]{images/pigalg.png}
\centering
\includegraphics[width=0.25\textwidth]{images/pigalg.png}
\end{figure}
\noindent
@ -22,8 +22,8 @@ Let's review the definitions. A monad is an endofunctor $m$
equipped with two natural transformations that satisfy some coherence
conditions. The components of these transformations at $a$ are:
\begin{align*}
\eta_a &\Colon a \to m\ a \\
\mu_a &\Colon m\ (m\ a) \to m\ a
\eta_a & \Colon a \to m\ a \\
\mu_a & \Colon m\ (m\ a) \to m\ a
\end{align*}
An algebra for the same endofunctor is a selection of a particular
object --- the carrier $a$ --- together with the morphism:
@ -53,8 +53,8 @@ $T$ in anticipation of what follows):
\centering
\begin{tikzcd}[column sep=large, row sep=large]
a \arrow[rd, equal] \arrow[r, "\eta_a"]
& Ta \arrow[d, "alg"] \\
& a
& Ta \arrow[d, "alg"] \\
& a
\end{tikzcd}
\end{subfigure}
\hspace{1cm}
@ -62,9 +62,9 @@ $T$ in anticipation of what follows):
\centering
\begin{tikzcd}[column sep=large, row sep=large]
T(Ta) \arrow[r, "T\ alg"] \arrow[d, "\mu_a"]
& Ta \arrow[d, "alg"] \\
& Ta \arrow[d, "alg"] \\
Ta \arrow[r, "alg"]
& a
& a
\end{tikzcd}
\end{subfigure}
\end{figure}
@ -130,8 +130,8 @@ evaluator.
We still have to show that this is a T-algebra. For that, two coherence
conditions must be satisfied:
\begin{align*}
alg &\circ \eta_{Ta} = \id_{Ta} \\
alg &\circ \mu_a = alg \circ T\ alg
alg & \circ \eta_{Ta} = \id_{Ta} \\
alg & \circ \mu_a = alg \circ T\ alg
\end{align*}
But these are just monadic laws, if you plug in $\mu$ for the
algebra.
@ -174,13 +174,13 @@ diagram that makes $f$ a T-algebra may be re-interpreted to show
that it's a homomorphism of T-algebras:
\begin{figure}[H]
\centering
\begin{tikzcd}[column sep=large, row sep=large]
T(Ta) \arrow[r, "T f"] \arrow[d, "\mu_a"]
& Ta \arrow[d, "f"] \\
Ta \arrow[r, "f"]
& a
\end{tikzcd}
\centering
\begin{tikzcd}[column sep=large, row sep=large]
T(Ta) \arrow[r, "T f"] \arrow[d, "\mu_a"]
& Ta \arrow[d, "f"] \\
Ta \arrow[r, "f"]
& a
\end{tikzcd}
\end{figure}
\noindent
@ -197,8 +197,8 @@ counit satisfy triangular identities. These are:
\centering
\begin{tikzcd}[column sep=large, row sep=large]
Ta \arrow[rd, equal] \arrow[r, "T \eta_a"]
& T(Ta) \arrow[d, "\mu_a"] \\
& Ta
& T(Ta) \arrow[d, "\mu_a"] \\
& Ta
\end{tikzcd}
\end{subfigure}%
\hspace{1cm}
@ -206,8 +206,8 @@ counit satisfy triangular identities. These are:
\centering
\begin{tikzcd}[column sep=large, row sep=large]
a \arrow[rd, equal] \arrow[r, "\eta_a"]
& Ta \arrow[d, "f"] \\
& a
& Ta \arrow[d, "f"] \\
& a
\end{tikzcd}
\end{subfigure}
\end{figure}
@ -260,20 +260,20 @@ Composition of morphisms in the Kleisli category is defined in terms of
monadic composition of Kleisli arrows. For instance, let's compose
$g_{\cat{K}}$ after $f_{\cat{K}}$. In the Kleisli category we have:
\begin{gather*}
f_{\cat{K}} \Colon a \to b \\
g_{\cat{K}} \Colon b \to c
f_{\cat{K}} \Colon a \to b \\
g_{\cat{K}} \Colon b \to c
\end{gather*}
which, in the category $\cat{C}$, corresponds to:
\begin{gather*}
f \Colon a \to T\ b \\
g \Colon b \to T\ c
f \Colon a \to T\ b \\
g \Colon b \to T\ c
\end{gather*}
We define the composition:
\[h_{\cat{K}} = g_{\cat{K}} \circ f_{\cat{K}}\]
as a Kleisli arrow in $\cat{C}$
\begin{align*}
h &\Colon a \to T\ c \\
h &= \mu \circ (T\ g) \circ f
h & \Colon a \to T\ c \\
h & = \mu \circ (T\ g) \circ f
\end{align*}
In Haskell we would write it as:
@ -330,8 +330,8 @@ with a comonad. They make the following diagrams commute:
\centering
\begin{tikzcd}[column sep=large, row sep=large]
a \arrow[rd, equal]
& Wa \arrow[l, "\epsilon_a"'] \\
& a \arrow[u, "coa"']
& Wa \arrow[l, "\epsilon_a"'] \\
& a \arrow[u, "coa"']
\end{tikzcd}
\end{subfigure}%
\hspace{1cm}
@ -339,9 +339,9 @@ with a comonad. They make the following diagrams commute:
\centering
\begin{tikzcd}[column sep=large, row sep=large]
W(Wa)
& Wa \arrow[l, "W\ coa"'] \\
& Wa \arrow[l, "W\ coa"'] \\
Wa \arrow[u, "\delta_a"]
& a \arrow[u, "coa"] \arrow[l, "coa"']
& a \arrow[u, "coa"] \arrow[l, "coa"']
\end{tikzcd}
\end{subfigure}
\end{figure}
@ -377,8 +377,8 @@ for the functor $Store\ s$:
\src{snippet07}
This coalgebra can be also expressed as a pair of functions:
\begin{align*}
set &\Colon a \to s \to a \\
get &\Colon a \to s
set & \Colon a \to s \to a \\
get & \Colon a \to s
\end{align*}
(Think of $a$ as standing for ``all,'' and $s$ as a
``small'' part of it.) In terms of this pair, we have:
@ -433,14 +433,14 @@ the \code{Store} functor.
\section{Challenges}
\begin{enumerate}
\tightlist
\item
What is the action of the free functor
$F \Colon C \to C^T$ on morphisms. Hint: use the
naturality condition for monadic $\mu$.
\item
Define the adjunction:
\[U^W \dashv F^W\]
\item
Prove that the above adjunction reproduces the original comonad.
\tightlist
\item
What is the action of the free functor
$F \Colon C \to C^T$ on morphisms. Hint: use the
naturality condition for monadic $\mu$.
\item
Define the adjunction:
\[U^W \dashv F^W\]
\item
Prove that the above adjunction reproduces the original comonad.
\end{enumerate}

View File

@ -1,8 +1,8 @@
% !TEX root = ../ctfp-print.tex
\ifdefined\OPTCustomLanguage{%
\chapter*{A note from the editor}
\addcontentsline{toc}{chapter}{A note from the editor}
\input{content/\OPTCustomLanguage/editor-note}
}
\chapter*{A note from the editor}
\addcontentsline{toc}{chapter}{A note from the editor}
\input{content/\OPTCustomLanguage/editor-note}
}
\fi

View File

@ -13,18 +13,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -51,17 +40,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-ocaml}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -72,11 +61,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -91,27 +80,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\bartosz
&
&
\vspace{5pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -13,18 +13,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -51,17 +40,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-reason}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -72,11 +61,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -91,27 +80,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\bartosz
&
&
\vspace{5pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -13,18 +13,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -51,17 +40,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-scala}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -72,11 +61,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -91,27 +80,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\bartosz
&
&
\vspace{5pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -46,16 +46,16 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\vspace{2cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -66,11 +66,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -85,27 +85,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\bartosz
&
&
\vspace{5pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -14,26 +14,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
% \setmainfont{AlegreyaSans-Regular}[
% BoldFont={AlegreyaSans-Bold},
% ItalicFont={AlegreyaSans-Italic},
% UprightFeatures={SmallCapsFont=AlegreyaSansSC-Regular},
% ItalicFeatures={SmallCapsFont=AlegreyaSansSC-Italic},
% BoldFeatures={SmallCapsFont=AlegreyaSansSC-Bold},
% BoldItalicFeatures={SmallCapsFont=AlegreyaSansSC-BoldItalic},
% ]
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -60,17 +41,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-ocaml}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -81,11 +62,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -101,27 +82,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\vspace{5pt}
\bartosz
&
&
\vspace{10pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -14,26 +14,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
% \setmainfont{AlegreyaSans-Regular}[
% BoldFont={AlegreyaSans-Bold},
% ItalicFont={AlegreyaSans-Italic},
% UprightFeatures={SmallCapsFont=AlegreyaSansSC-Regular},
% ItalicFeatures={SmallCapsFont=AlegreyaSansSC-Italic},
% BoldFeatures={SmallCapsFont=AlegreyaSansSC-Bold},
% BoldItalicFeatures={SmallCapsFont=AlegreyaSansSC-BoldItalic},
% ]
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -60,17 +41,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-reason}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -81,11 +62,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -101,27 +82,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\vspace{5pt}
\bartosz
&
&
\vspace{10pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -14,18 +14,7 @@
\usetikzlibrary{calc,positioning, shadings}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\setmainfont[
Path=fonts/,
Extension=.otf,
UprightFont=*-Regular,
ItalicFont=*-Italic,
BoldFont=*-Bold,
UprightFeatures={SmallCapsFont=*SC-Regular},
ItalicFeatures={SmallCapsFont=*SC-Italic},
BoldFeatures={SmallCapsFont=*SC-Bold},
BoldItalicFeatures={SmallCapsFont=*SC-BoldItalic},
]{AlegreyaSans}
\usepackage{Alegreya}
\newcommand{\olpath}{../}
\newcommand{\whitebg}[1]{%
@ -52,17 +41,17 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\input{ribbon-scala}
\vspace{1.1cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -73,11 +62,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -93,27 +82,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\vspace{5pt}
\bartosz
&
&
\vspace{10pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -46,16 +46,16 @@
\definecolor{BackgroundColor}{HTML}{f3f6ed}
\definecolor{SpineBackColor}{HTML}{262626}
\begin{document}
\begin{document}
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\begin{bookcover}
\bookcovercomponent{color}{bg whole}{color=BackgroundColor}
\bookcovercomponent{color}{spine}{color=SpineBackColor}
\bookcovercomponent{normal}{front}{
\vspace{2cm}
\begin{center}
\fontsize{40pt}{5em}\selectfont\bfseries
CATEGORY THEORY \\FOR PROGRAMMERS
CATEGORY THEORY \\FOR PROGRAMMERS
\vfil
\hspace*{-.8cm}\includegraphics[width=.5\coverwidth]{piggie}
\linebreak
@ -66,11 +66,11 @@
\vspace*{1cm}
\end{center}}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\bookcovercomponent{center}{spine}{
\rotatebox[origin=c]{-90}{\color{orange}
\Huge\bfseries Category Theory for Programmers \hspace{2em} Bartosz Milewski}}
\bookcovercomponent{normal}{back}{%
\bookcovercomponent{normal}{back}{%
\begin{minipage}[b][\coverheight][t]{\coverwidth}
\begin{center}
\vspace{1cm}
@ -85,27 +85,27 @@
\begin{tabular}[h]{p{3.4cm} p{\textwidth}}
\bartosz
&
&
\vspace{5pt}
\begin{minipage}[b]{.58\coverwidth}
\fontsize{11pt}{1.4em}\selectfont\textit{Category Theory for Programmers}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
is a series of blog posts by Bartosz Milewski, originally posted on bartoszmilewski.com.\\
Edited by Igal Tabachnik. Licenced under CC BY-SA 4.0.\\
\end{minipage}
\end{tabular}
\begin{flushright}
\vspace{-2.6cm}
\begin{minipage}[b]{4cm}
\raggedleft
\whitebg{fig/icons/by}
\whitebg{fig/icons/cc}
\whitebg{fig/icons/sa}
\centering\footnotesize{\texttt{\OPTversion}}
\end{minipage}
\end{flushright}
\end{minipage}
\end{center}
\end{minipage}
}
\end{bookcover}
\end{bookcover}
\end{document}

View File

@ -9,22 +9,22 @@
overlay,
remember picture,
ribbon/.style={anchor=center, rotate = 45,
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\fill [BurntOrange!20] (A) -- (A') -- (B') -- (B) -- cycle;
\fill [BurntOrange!20] (A) -- (A') -- (B') -- (B) -- cycle;
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.15\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/ocaml}}
\hspace{.5mm} OCaml Edition
};
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.15\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/ocaml}}
\hspace{.5mm} OCaml Edition
};
\end{tikzpicture}

View File

@ -9,22 +9,22 @@
overlay,
remember picture,
ribbon/.style={anchor=center, rotate = 45,
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\fill [RedOrange!20] (A) -- (A') -- (B') -- (B) -- cycle;
\fill [RedOrange!20] (A) -- (A') -- (B') -- (B) -- cycle;
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.15\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/reason}}
\hspace{.5mm} ReasonML Edition
};
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.15\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/reason}}
\hspace{.5mm} ReasonML Edition
};
\end{tikzpicture}

View File

@ -5,22 +5,22 @@
overlay,
remember picture,
ribbon/.style={anchor=center, rotate = 45,
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
font={\fontsize{22}{1}\selectfont\bfseries}}
]
\coordinate (A) at ($ (current page.south east) + (-\stripskip,0) $);% <-- changed coordinate from 'north' to south'
\coordinate (A') at ($(A) + (-\stripwidth,0) $);
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\coordinate (B) at ($ (current page.south east) + (0,\stripskip) $);% <-- changed coordinate from 'north' to south' and sign for \stripskip
\coordinate (B') at ($(B) + (0,\stripwidth) $);% <-- changed sign for \stripskip
\fill [red!20] (A) -- (A') -- (B') -- (B) -- cycle;
\fill [red!20] (A) -- (A') -- (B') -- (B) -- cycle;
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\coordinate (tempA) at ($(A)!.5!(A')$);
\coordinate (tempB) at ($(B)!.5!(B')$);
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.30\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/scala}}
\hspace{.5mm} Scala Edition
};
\node [ribbon](text) at ($(tempA)!.5!(tempB)$) {
\raisebox{-.30\height}{\includegraphics[width=.8cm]{\olpath/fig/icons/scala}}
\hspace{.5mm} Scala Edition
};
\end{tikzpicture}

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More