├── english ├── images ├── base.css ├── index.md ├── metadata.yaml ├── license.md ├── acknowledgments.md ├── defaults.yaml ├── preface.md ├── index_html.md ├── part3 │ ├── ch01.md │ └── ch03.md └── part2 │ └── ch01.md ├── japanese ├── base.css ├── images ├── part1 │ ├── images │ ├── ch01.md │ └── ch03.md ├── index.md ├── license.md ├── metadata.yaml ├── acknowledgments.md ├── style.tex ├── index.dic ├── defaults.yaml ├── preface.md ├── part3 │ ├── ch01.md │ ├── ch03.md │ ├── ch13.md │ ├── ch15.md │ └── ch04.md ├── part2 │ ├── ch01.md │ ├── ch03.md │ ├── ch05.md │ ├── ch06.md │ └── ch04.md └── index_html.md ├── frontmatter.tex ├── mainmatter.tex ├── _config.yml ├── ensuremath.sed ├── googlefe211dcb8292e32b.html ├── images ├── id.jpg ├── alg.png ├── alg2.png ├── alg3.png ├── alg4.png ├── alg5.png ├── alg6.png ├── alg7.png ├── cone.jpg ├── end.jpg ├── end1.jpg ├── kan2.jpg ├── kan5.jpg ├── kan6.jpg ├── kan7.jpg ├── pair.jpg ├── span.png ├── true.jpg ├── two.jpg ├── adj-1.jpg ├── alg3a.png ├── assoc.png ├── assoc1.png ├── assoc2.png ├── bicat.png ├── bimap.jpg ├── bimonad.png ├── bunnies.jpg ├── classes.jpg ├── colimit.jpg ├── dimap.jpg ├── end-1.jpg ├── end-2.jpg ├── end-21.jpg ├── end-31.jpg ├── exptree.png ├── feynman.jpg ├── final.jpg ├── first.jpg ├── functor.jpg ├── hom-set.jpg ├── initial.jpg ├── kan10a.jpg ├── kan10b.jpg ├── kan112.jpg ├── kan12.jpg ├── kan13.jpg ├── kan14.jpg ├── kan15.jpg ├── kan81.jpg ├── kan92.jpg ├── monad.png ├── monoid.jpg ├── mortar.jpg ├── notmono.jpg ├── pigalg.png ├── second.jpg ├── sheets.png ├── snell.jpg ├── spanmul.png ├── twocat.png ├── unitmon.jpg ├── yoneda1.png ├── yoneda2.png ├── yoneda3.png ├── yoneda4.png ├── yoneda5.png ├── 2_natcomp.jpg ├── adj-expo.jpg ├── adj-unit.jpg ├── assocmon.png ├── asteroids.png ├── bifunctor.jpg ├── compspan.png ├── forgetful.jpg ├── freeimage.jpg ├── functorid.jpg ├── hom-set2.jpg ├── horizcomp.png ├── img_1299.jpg ├── img_1329.jpg ├── img_1330.jpg ├── lawvere1.png ├── liftpower.png ├── monoid-1.jpg ├── morphspan.png ├── piggyback.jpg ├── pullback.jpg ├── pullspan.png ├── sideways.jpg ├── spanmonad.png ├── spanunit.png ├── twodelta.jpg ├── 1_functors.jpg ├── 3_naturality.jpg ├── 4_transport.jpg ├── 5_vertical.jpg ├── 6a_vertical.jpg ├── 7_cathomset.jpg ├── 8_cat-2-cat.jpg ├── 9_horizontal.jpg ├── adj-counit.jpg ├── adj-homsets.jpg ├── adj-product.jpg ├── assoctensor.jpg ├── composition.jpg ├── continuity.jpg ├── functionset.jpg ├── functormaybe.jpg ├── hom-functor.jpg ├── monoidhomset.jpg ├── monomorphism.jpg ├── natmapping.jpg ├── naturality.jpg ├── productcone.jpg ├── pullbackcone.jpg ├── set-hom-set.jpg ├── uniqueness.jpg ├── unitlawcomp.png ├── 10_horizontal.jpg ├── adj-productcat.jpg ├── conenaturality.jpg ├── contravariant.jpg ├── equalizercone.jpg ├── equilizerlimit.jpg ├── functorcompos.jpg ├── homsetmapping.jpg ├── monoid-pattern.jpg ├── monoid-ranking.jpg ├── not-a-product.jpg ├── productpattern.jpg ├── productranking.jpg ├── pullbacklimit.jpg ├── unitlawcomp-1.png ├── conecommutativity.jpg ├── coproductpattern.jpg ├── coproductranking.jpg ├── freemonadjunction.jpg ├── functionpattern.jpg ├── functionranking.jpg ├── productcandidates.jpg ├── subsetinjection.jpg ├── yoneda-embedding.jpg ├── forgettingmorphisms.jpg ├── kan3-e1492120491591.jpg ├── yoneda-embedding-2.jpg ├── 6_verticalnaturality.jpg ├── kan31-e1492120512209.jpg ├── universalfunctionobject.jpg └── beauvais_interior_supports.jpg ├── fonts ├── incons-r-subset.woff ├── incons-rb-subset.woff ├── incons-ri-subset.woff └── fonts.css ├── packages.tex ├── .gitignore ├── codeblock.tex ├── category.tex ├── defaults-part2.yaml ├── defaults-part1.yaml ├── defaults-part3.yaml ├── defaults_html.yaml ├── README.md ├── monochrome-no-underline.theme ├── base.css └── html_templates └── toc-sidebar.html /english/images: -------------------------------------------------------------------------------- 1 | ../images -------------------------------------------------------------------------------- /english/base.css: -------------------------------------------------------------------------------- 1 | ../base.css -------------------------------------------------------------------------------- /japanese/base.css: -------------------------------------------------------------------------------- 1 | ../base.css -------------------------------------------------------------------------------- /japanese/images: -------------------------------------------------------------------------------- 1 | ../images -------------------------------------------------------------------------------- /frontmatter.tex: -------------------------------------------------------------------------------- 1 | \frontmatter 2 | -------------------------------------------------------------------------------- /japanese/part1/images: -------------------------------------------------------------------------------- 1 | ../../images -------------------------------------------------------------------------------- /mainmatter.tex: -------------------------------------------------------------------------------- 1 | \mainmatter 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - jekyll-sitemap 3 | -------------------------------------------------------------------------------- /english/index.md: -------------------------------------------------------------------------------- 1 | 2 | \cleardoublepage 3 | \printindex 4 | -------------------------------------------------------------------------------- /japanese/index.md: -------------------------------------------------------------------------------- 1 | \cleardoublepage 2 | \printindex 3 | -------------------------------------------------------------------------------- /ensuremath.sed: -------------------------------------------------------------------------------- 1 | s/∘/\\ensuremath{\\circ}/ 2 | s/∷/\\ensuremath{\\Colon}/ 3 | -------------------------------------------------------------------------------- /googlefe211dcb8292e32b.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlefe211dcb8292e32b.html -------------------------------------------------------------------------------- /images/id.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/id.jpg -------------------------------------------------------------------------------- /images/alg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg.png -------------------------------------------------------------------------------- /images/alg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg2.png -------------------------------------------------------------------------------- /images/alg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg3.png -------------------------------------------------------------------------------- /images/alg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg4.png -------------------------------------------------------------------------------- /images/alg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg5.png -------------------------------------------------------------------------------- /images/alg6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg6.png -------------------------------------------------------------------------------- /images/alg7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg7.png -------------------------------------------------------------------------------- /images/cone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/cone.jpg -------------------------------------------------------------------------------- /images/end.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end.jpg -------------------------------------------------------------------------------- /images/end1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end1.jpg -------------------------------------------------------------------------------- /images/kan2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan2.jpg -------------------------------------------------------------------------------- /images/kan5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan5.jpg -------------------------------------------------------------------------------- /images/kan6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan6.jpg -------------------------------------------------------------------------------- /images/kan7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan7.jpg -------------------------------------------------------------------------------- /images/pair.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pair.jpg -------------------------------------------------------------------------------- /images/span.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/span.png -------------------------------------------------------------------------------- /images/true.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/true.jpg -------------------------------------------------------------------------------- /images/two.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/two.jpg -------------------------------------------------------------------------------- /images/adj-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-1.jpg -------------------------------------------------------------------------------- /images/alg3a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/alg3a.png -------------------------------------------------------------------------------- /images/assoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/assoc.png -------------------------------------------------------------------------------- /images/assoc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/assoc1.png -------------------------------------------------------------------------------- /images/assoc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/assoc2.png -------------------------------------------------------------------------------- /images/bicat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/bicat.png -------------------------------------------------------------------------------- /images/bimap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/bimap.jpg -------------------------------------------------------------------------------- /images/bimonad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/bimonad.png -------------------------------------------------------------------------------- /images/bunnies.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/bunnies.jpg -------------------------------------------------------------------------------- /images/classes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/classes.jpg -------------------------------------------------------------------------------- /images/colimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/colimit.jpg -------------------------------------------------------------------------------- /images/dimap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/dimap.jpg -------------------------------------------------------------------------------- /images/end-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end-1.jpg -------------------------------------------------------------------------------- /images/end-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end-2.jpg -------------------------------------------------------------------------------- /images/end-21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end-21.jpg -------------------------------------------------------------------------------- /images/end-31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/end-31.jpg -------------------------------------------------------------------------------- /images/exptree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/exptree.png -------------------------------------------------------------------------------- /images/feynman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/feynman.jpg -------------------------------------------------------------------------------- /images/final.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/final.jpg -------------------------------------------------------------------------------- /images/first.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/first.jpg -------------------------------------------------------------------------------- /images/functor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functor.jpg -------------------------------------------------------------------------------- /images/hom-set.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/hom-set.jpg -------------------------------------------------------------------------------- /images/initial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/initial.jpg -------------------------------------------------------------------------------- /images/kan10a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan10a.jpg -------------------------------------------------------------------------------- /images/kan10b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan10b.jpg -------------------------------------------------------------------------------- /images/kan112.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan112.jpg -------------------------------------------------------------------------------- /images/kan12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan12.jpg -------------------------------------------------------------------------------- /images/kan13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan13.jpg -------------------------------------------------------------------------------- /images/kan14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan14.jpg -------------------------------------------------------------------------------- /images/kan15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan15.jpg -------------------------------------------------------------------------------- /images/kan81.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan81.jpg -------------------------------------------------------------------------------- /images/kan92.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan92.jpg -------------------------------------------------------------------------------- /images/monad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monad.png -------------------------------------------------------------------------------- /images/monoid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monoid.jpg -------------------------------------------------------------------------------- /images/mortar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/mortar.jpg -------------------------------------------------------------------------------- /images/notmono.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/notmono.jpg -------------------------------------------------------------------------------- /images/pigalg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pigalg.png -------------------------------------------------------------------------------- /images/second.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/second.jpg -------------------------------------------------------------------------------- /images/sheets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/sheets.png -------------------------------------------------------------------------------- /images/snell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/snell.jpg -------------------------------------------------------------------------------- /images/spanmul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/spanmul.png -------------------------------------------------------------------------------- /images/twocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/twocat.png -------------------------------------------------------------------------------- /images/unitmon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/unitmon.jpg -------------------------------------------------------------------------------- /images/yoneda1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda1.png -------------------------------------------------------------------------------- /images/yoneda2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda2.png -------------------------------------------------------------------------------- /images/yoneda3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda3.png -------------------------------------------------------------------------------- /images/yoneda4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda4.png -------------------------------------------------------------------------------- /images/yoneda5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda5.png -------------------------------------------------------------------------------- /images/2_natcomp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/2_natcomp.jpg -------------------------------------------------------------------------------- /images/adj-expo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-expo.jpg -------------------------------------------------------------------------------- /images/adj-unit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-unit.jpg -------------------------------------------------------------------------------- /images/assocmon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/assocmon.png -------------------------------------------------------------------------------- /images/asteroids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/asteroids.png -------------------------------------------------------------------------------- /images/bifunctor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/bifunctor.jpg -------------------------------------------------------------------------------- /images/compspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/compspan.png -------------------------------------------------------------------------------- /images/forgetful.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/forgetful.jpg -------------------------------------------------------------------------------- /images/freeimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/freeimage.jpg -------------------------------------------------------------------------------- /images/functorid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functorid.jpg -------------------------------------------------------------------------------- /images/hom-set2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/hom-set2.jpg -------------------------------------------------------------------------------- /images/horizcomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/horizcomp.png -------------------------------------------------------------------------------- /images/img_1299.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/img_1299.jpg -------------------------------------------------------------------------------- /images/img_1329.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/img_1329.jpg -------------------------------------------------------------------------------- /images/img_1330.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/img_1330.jpg -------------------------------------------------------------------------------- /images/lawvere1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/lawvere1.png -------------------------------------------------------------------------------- /images/liftpower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/liftpower.png -------------------------------------------------------------------------------- /images/monoid-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monoid-1.jpg -------------------------------------------------------------------------------- /images/morphspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/morphspan.png -------------------------------------------------------------------------------- /images/piggyback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/piggyback.jpg -------------------------------------------------------------------------------- /images/pullback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pullback.jpg -------------------------------------------------------------------------------- /images/pullspan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pullspan.png -------------------------------------------------------------------------------- /images/sideways.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/sideways.jpg -------------------------------------------------------------------------------- /images/spanmonad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/spanmonad.png -------------------------------------------------------------------------------- /images/spanunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/spanunit.png -------------------------------------------------------------------------------- /images/twodelta.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/twodelta.jpg -------------------------------------------------------------------------------- /images/1_functors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/1_functors.jpg -------------------------------------------------------------------------------- /images/3_naturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/3_naturality.jpg -------------------------------------------------------------------------------- /images/4_transport.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/4_transport.jpg -------------------------------------------------------------------------------- /images/5_vertical.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/5_vertical.jpg -------------------------------------------------------------------------------- /images/6a_vertical.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/6a_vertical.jpg -------------------------------------------------------------------------------- /images/7_cathomset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/7_cathomset.jpg -------------------------------------------------------------------------------- /images/8_cat-2-cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/8_cat-2-cat.jpg -------------------------------------------------------------------------------- /images/9_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/9_horizontal.jpg -------------------------------------------------------------------------------- /images/adj-counit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-counit.jpg -------------------------------------------------------------------------------- /images/adj-homsets.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-homsets.jpg -------------------------------------------------------------------------------- /images/adj-product.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-product.jpg -------------------------------------------------------------------------------- /images/assoctensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/assoctensor.jpg -------------------------------------------------------------------------------- /images/composition.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/composition.jpg -------------------------------------------------------------------------------- /images/continuity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/continuity.jpg -------------------------------------------------------------------------------- /images/functionset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functionset.jpg -------------------------------------------------------------------------------- /images/functormaybe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functormaybe.jpg -------------------------------------------------------------------------------- /images/hom-functor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/hom-functor.jpg -------------------------------------------------------------------------------- /images/monoidhomset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monoidhomset.jpg -------------------------------------------------------------------------------- /images/monomorphism.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monomorphism.jpg -------------------------------------------------------------------------------- /images/natmapping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/natmapping.jpg -------------------------------------------------------------------------------- /images/naturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/naturality.jpg -------------------------------------------------------------------------------- /images/productcone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/productcone.jpg -------------------------------------------------------------------------------- /images/pullbackcone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pullbackcone.jpg -------------------------------------------------------------------------------- /images/set-hom-set.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/set-hom-set.jpg -------------------------------------------------------------------------------- /images/uniqueness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/uniqueness.jpg -------------------------------------------------------------------------------- /images/unitlawcomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/unitlawcomp.png -------------------------------------------------------------------------------- /images/10_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/10_horizontal.jpg -------------------------------------------------------------------------------- /images/adj-productcat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/adj-productcat.jpg -------------------------------------------------------------------------------- /images/conenaturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/conenaturality.jpg -------------------------------------------------------------------------------- /images/contravariant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/contravariant.jpg -------------------------------------------------------------------------------- /images/equalizercone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/equalizercone.jpg -------------------------------------------------------------------------------- /images/equilizerlimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/equilizerlimit.jpg -------------------------------------------------------------------------------- /images/functorcompos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functorcompos.jpg -------------------------------------------------------------------------------- /images/homsetmapping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/homsetmapping.jpg -------------------------------------------------------------------------------- /images/monoid-pattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monoid-pattern.jpg -------------------------------------------------------------------------------- /images/monoid-ranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/monoid-ranking.jpg -------------------------------------------------------------------------------- /images/not-a-product.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/not-a-product.jpg -------------------------------------------------------------------------------- /images/productpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/productpattern.jpg -------------------------------------------------------------------------------- /images/productranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/productranking.jpg -------------------------------------------------------------------------------- /images/pullbacklimit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/pullbacklimit.jpg -------------------------------------------------------------------------------- /images/unitlawcomp-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/unitlawcomp-1.png -------------------------------------------------------------------------------- /fonts/incons-r-subset.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/fonts/incons-r-subset.woff -------------------------------------------------------------------------------- /fonts/incons-rb-subset.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/fonts/incons-rb-subset.woff -------------------------------------------------------------------------------- /fonts/incons-ri-subset.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/fonts/incons-ri-subset.woff -------------------------------------------------------------------------------- /images/conecommutativity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/conecommutativity.jpg -------------------------------------------------------------------------------- /images/coproductpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/coproductpattern.jpg -------------------------------------------------------------------------------- /images/coproductranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/coproductranking.jpg -------------------------------------------------------------------------------- /images/freemonadjunction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/freemonadjunction.jpg -------------------------------------------------------------------------------- /images/functionpattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functionpattern.jpg -------------------------------------------------------------------------------- /images/functionranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/functionranking.jpg -------------------------------------------------------------------------------- /images/productcandidates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/productcandidates.jpg -------------------------------------------------------------------------------- /images/subsetinjection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/subsetinjection.jpg -------------------------------------------------------------------------------- /images/yoneda-embedding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda-embedding.jpg -------------------------------------------------------------------------------- /english/metadata.yaml: -------------------------------------------------------------------------------- 1 | title: Category Theory for Programmers 2 | author: Bartosz Milewski 3 | cover-image: images/monoid.jpg 4 | -------------------------------------------------------------------------------- /images/forgettingmorphisms.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/forgettingmorphisms.jpg -------------------------------------------------------------------------------- /images/kan3-e1492120491591.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan3-e1492120491591.jpg -------------------------------------------------------------------------------- /images/yoneda-embedding-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/yoneda-embedding-2.jpg -------------------------------------------------------------------------------- /images/6_verticalnaturality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/6_verticalnaturality.jpg -------------------------------------------------------------------------------- /images/kan31-e1492120512209.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/kan31-e1492120512209.jpg -------------------------------------------------------------------------------- /images/universalfunctionobject.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/universalfunctionobject.jpg -------------------------------------------------------------------------------- /images/beauvais_interior_supports.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktgw0316/milewski-ctfp-markdown/HEAD/images/beauvais_interior_supports.jpg -------------------------------------------------------------------------------- /japanese/license.md: -------------------------------------------------------------------------------- 1 | \clearpage 2 | 3 | # ライセンス {-} 4 | 5 | この作品は、クリエイティブ・コモンズの 表示 - 継承 4.0 国際 ライセンスで提供されています。ライセンスの写しをご覧になるには、をご覧頂くか、Creative Commons, PO Box 1866, Mountain View, CA 94042, USA までお手紙をお送りください。 6 | -------------------------------------------------------------------------------- /packages.tex: -------------------------------------------------------------------------------- 1 | \usepackage{caption} \captionsetup[figure]{labelformat=empty,font={small,sf}} 2 | \usepackage{subfigure} 3 | \usepackage{tikz-cd} 4 | \usepackage[framemethod=TikZ]{mdframed} 5 | \usepackage{float} 6 | \usepackage{makeidx} 7 | \usepackage{fancyvrb} 8 | \makeindex 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | documents/ 3 | node_modules/ 4 | pytermex/ 5 | termextract*/ 6 | tests/ 7 | test_data/ 8 | */images 9 | *.aux 10 | *.dvi 11 | *.epub 12 | *.idx 13 | *.ilg 14 | *.ind 15 | *.json 16 | *.log 17 | *.pdf 18 | *.py 19 | *.tex 20 | *.toc 21 | *.txt 22 | *.zip 23 | -------------------------------------------------------------------------------- /english/license.md: -------------------------------------------------------------------------------- 1 | # License {-} 2 | 3 | This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 4 | -------------------------------------------------------------------------------- /japanese/metadata.yaml: -------------------------------------------------------------------------------- 1 | title: プログラマーのための圏論 2 | author: バルトシュ・ミレフスキー著 北川雅裕訳 3 | date: \today 4 | creator: 5 | - role: author 6 | text: バルトシュ・ミレフスキー 7 | - role: translator 8 | text: 北川雅裕 9 | lang: ja-JP 10 | URL: https://github.com/ktgw0316/milewski-ctfp-markdown/ 11 | rights: (C) 2018 Bartosz Milewski, CC BY-SA-4.0 12 | cover-image: images/monoid.jpg 13 | -------------------------------------------------------------------------------- /codeblock.tex: -------------------------------------------------------------------------------- 1 | % Codeblock style 2 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},fontsize=\small} 3 | \mdfsetup{ 4 | linecolor=gray!20, 5 | linewidth=2pt, 6 | topline=false, 7 | bottomline=false, 8 | rightline=false, 9 | skipabove=1ex, 10 | skipbelow=1ex, 11 | } 12 | \surroundwithmdframed[linewidth=2pt]{Highlighting} 13 | -------------------------------------------------------------------------------- /japanese/acknowledgments.md: -------------------------------------------------------------------------------- 1 | \clearpage 2 | 3 | # 謝辞 {-} 4 | 5 | 私の計算と論理をチェックしてくれたEdward KmettとGershom Bazermanに感謝したい。私の誤りを訂正し、本書を改善してくれた大勢のボランティアに感謝している。 6 | 7 | Andrew Suttonには、自身とBjarne Stroustrupの最新の提案に沿ってC++のモノイドのコンセプトコードを書き直してくれたことに感謝したい。 8 | 9 | Eric Nieblerには、草稿を読み、C++14の高度な機能を用いて型推論を進める`compose`の巧妙な実装を提供してくれたことに感謝している。昔ながらのテンプレートマジックを使って型トレイトと同じことをしていたセクションをすべてカットできた。 10 | せいせいした! 11 | -------------------------------------------------------------------------------- /category.tex: -------------------------------------------------------------------------------- 1 | \newcommand{\cat}{\mathbf} 2 | \newcommand{\idarrow}[1][]{% 3 | \mathbf{id}_{#1}% 4 | } 5 | \newcommand{\Lim}[1][]{% 6 | \mathbf{Lim}{#1}% 7 | } 8 | \newcommand{\Set}{\cat{Set}} 9 | \newcommand{\Rel}{\cat{Rel}} 10 | \newcommand{\Cat}{\cat{Cat}} 11 | \newcommand{\id}{\mathbf{id}} 12 | \newcommand{\Ran}{\mathbf{Ran}} 13 | \newcommand{\Lan}{\mathbf{Lan}} 14 | \newcommand{\Hask}{\mathbf{Hask}} 15 | \newcommand{\Fop}{\cat{F}^\mathit{op}} 16 | \newcommand{\Nat}{\mathit{Nat}} 17 | -------------------------------------------------------------------------------- /fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* Inconsolata LGC */ 2 | 3 | @font-face { 4 | font-family: 'Inconsolata LGC'; 5 | src: url('incons-r-subset.woff'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | @font-face { 11 | font-family: 'Inconsolata LGC'; 12 | src: url('incons-ri-subset.woff'); 13 | font-weight: normal; 14 | font-style: italic; 15 | } 16 | 17 | @font-face { 18 | font-family: 'Inconsolata LGC'; 19 | src: url('incons-rb-subset.woff'); 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | -------------------------------------------------------------------------------- /japanese/style.tex: -------------------------------------------------------------------------------- 1 | \renewcommand{\labelenumi}{\theenumi. } 2 | \renewcommand{\labelenumii}{(\theenumii) } 3 | \setlength{\parindent}{1\zw} 4 | \setlength{\parskip}{0pt} 5 | 6 | % ダッシュをつなげる 7 | % cf. https://qiita.com/isari/items/1d0b60b76c7ef168e376 8 | \usepackage{newunicodechar} 9 | \makeatletter 10 | \chardef\my@J@horizbar="2015% Unicodeの2015 11 | \newunicodechar{―}{\x@my@dash} 12 | \def\x@my@dash{\@ifnextchar―{% 13 | \my@J@horizbar\kern-.5\zw\my@J@horizbar\kern-.5\zw}{% 14 | \my@J@horizbar}} 15 | % 次が―なら2回目のkernまでを、そうでないなら普通の―を出力 16 | \makeatother 17 | -------------------------------------------------------------------------------- /english/acknowledgments.md: -------------------------------------------------------------------------------- 1 | # Acknowledgments {-} 2 | 3 | I’d like to thank Edward Kmett and Gershom Bazerman for checking my math 4 | and logic. I'm grateful to many volunteers who corrected my mistakes and improved the book. 5 | 6 | I’d like to thank Andrew Sutton for rewriting my C++ monoid concept 7 | code according to his and Bjarne Stroustrup’s latest proposal. 8 | 9 | I'm grateful to Eric Niebler for reading the draft and providing the 10 | clever implementation of `compose` that uses advanced features of 11 | C++14 to drive type inference. I was able to cut the whole section of 12 | old fashioned template magic that did the same thing using type traits. 13 | Good riddance! 14 | -------------------------------------------------------------------------------- /defaults-part2.yaml: -------------------------------------------------------------------------------- 1 | # pdf 2 | to: latex 3 | pdf-engine: lualatex 4 | metadata: 5 | documentclass: jlreq 6 | variables: 7 | classoption: 8 | - book 9 | - paper=a5paper 10 | include-in-header: 11 | - ../packages.tex 12 | - ../codeblock.tex 13 | - style.tex 14 | - ../frontmatter.tex 15 | 16 | # common 17 | metadata-file: metadata.yaml 18 | from: markdown+smart 19 | highlight-style: ../monochrome-no-underline.theme 20 | table-of-contents: true 21 | toc-depth: 2 22 | top-level-division: chapter 23 | number-sections: true 24 | reference-location: section 25 | 26 | input-files: 27 | - ../category.tex 28 | - ../mainmatter.tex 29 | - part2/ch01.md 30 | - part2/ch02.md 31 | - part2/ch03.md 32 | - part2/ch04.md 33 | - part2/ch05.md 34 | - part2/ch06.md 35 | - license.md 36 | -------------------------------------------------------------------------------- /defaults-part1.yaml: -------------------------------------------------------------------------------- 1 | # pdf 2 | to: latex 3 | pdf-engine: lualatex 4 | metadata: 5 | documentclass: jlreq 6 | variables: 7 | classoption: 8 | - book 9 | - paper=a5paper 10 | include-in-header: 11 | - ../packages.tex 12 | - ../codeblock.tex 13 | - style.tex 14 | - ../frontmatter.tex 15 | 16 | # common 17 | metadata-file: metadata.yaml 18 | from: markdown+smart 19 | highlight-style: ../monochrome-no-underline.theme 20 | table-of-contents: true 21 | toc-depth: 2 22 | top-level-division: chapter 23 | number-sections: true 24 | reference-location: section 25 | 26 | input-files: 27 | - ../category.tex 28 | - preface.md 29 | - ../mainmatter.tex 30 | - part1/ch01.md 31 | - part1/ch02.md 32 | - part1/ch03.md 33 | - part1/ch04.md 34 | - part1/ch05.md 35 | - part1/ch06.md 36 | - part1/ch07.md 37 | - part1/ch08.md 38 | - part1/ch09.md 39 | - part1/ch10.md 40 | - license.md 41 | -------------------------------------------------------------------------------- /japanese/index.dic: -------------------------------------------------------------------------------- 1 | 一 いち 2 | 上 うえ 3 | 不動 ふどう 4 | 付き つき 5 | 余 よ 6 | 作用 さよう 7 | 全 ぜん 8 | 内部 ないぶ 9 | 冪 べき 10 | 前 ぜん 11 | 副 ふく 12 | 半 はん 13 | 単 たん 14 | 双 そう 15 | 反変 はんぺん 16 | 反対 はんたい 17 | 可能 かのう 18 | 台 だい 19 | 右 みぎ 20 | 合成 ごうせい 21 | 同値 どうち 22 | 同型 どうけい 23 | 圏 けん 24 | 型 かた 25 | 埋め込み うめこみ 26 | 基本 きほん 27 | 外延 がいえん 28 | 始代数 しだいすう 29 | 対称 たいしょう 30 | 対象 たいしょう 31 | 射 しゃ 32 | 層 そう 33 | 左 ひだり 34 | 忘却 ぼうきゃく 35 | 性 せい 36 | 恒等 こうとう 37 | 意味論 いみろん 38 | 成分 せいぶん 39 | 推論 すいろん 40 | 操作 そうさ 41 | 文脈 ぶんみゃく 42 | 方向 ほうこう 43 | 普遍 ふへん 44 | 条件 じょうけん 45 | 水平 すいへい 46 | 準 じゅん 47 | 点 てん 48 | 環 かん 49 | 的 てき 50 | 矢 や 51 | 積 せき 52 | 等化子 とうかし 53 | 等式 とうしき 54 | 米田 よねだ 55 | 純粋 じゅんすい 56 | 線形 せんけい 57 | 自己 じこ 58 | 自然 しぜん 59 | 自由 じゆう 60 | 表現 ひょうげん 61 | 表示 ひょうじ 62 | 計算 けいさん 63 | 証明 しょうめい 64 | 評価 ひょうか 65 | 豊穣 ほうじょう 66 | 述語 じゅつご 67 | 適用 てきよう 68 | 閉 へい 69 | 関係 かんけい 70 | 関手 かんしゅ 71 | 関数 かんすう 72 | 関連 かんれん 73 | 除いて のぞいて 74 | 随伴 ずいはん 75 | 集合 しゅうごう 76 | 順序 じゅんじょ 77 | 骨格 こっかく 78 | 理論 りろん 79 | -------------------------------------------------------------------------------- /defaults-part3.yaml: -------------------------------------------------------------------------------- 1 | # pdf 2 | to: latex 3 | pdf-engine: lualatex 4 | metadata: 5 | documentclass: jlreq 6 | variables: 7 | classoption: 8 | - book 9 | - paper=a5paper 10 | include-in-header: 11 | - ../packages.tex 12 | - ../codeblock.tex 13 | - style.tex 14 | - ../frontmatter.tex 15 | 16 | # common 17 | metadata-file: metadata.yaml 18 | from: markdown+smart 19 | highlight-style: ../monochrome-no-underline.theme 20 | table-of-contents: true 21 | toc-depth: 2 22 | top-level-division: chapter 23 | number-sections: true 24 | reference-location: section 25 | 26 | input-files: 27 | - ../category.tex 28 | - ../mainmatter.tex 29 | - part3/ch01.md 30 | - part3/ch02.md 31 | - part3/ch03.md 32 | - part3/ch04.md 33 | - part3/ch05.md 34 | - part3/ch06.md 35 | - part3/ch07.md 36 | - part3/ch08.md 37 | - part3/ch09.md 38 | - part3/ch10.md 39 | - part3/ch11.md 40 | - part3/ch12.md 41 | - part3/ch13.md 42 | - part3/ch14.md 43 | - part3/ch15.md 44 | - index.md 45 | - acknowledgments.md 46 | - license.md 47 | -------------------------------------------------------------------------------- /defaults_html.yaml: -------------------------------------------------------------------------------- 1 | # epub 2 | epub-metadata: metadata.yaml 3 | epub-chapter-level: 2 4 | epub-cover-image: images/monoid.jpg 5 | 6 | # html 7 | standalone: true 8 | html-math-method: 9 | method: mathml 10 | 11 | # common 12 | css: 13 | - base.css 14 | metadata-file: metadata.yaml 15 | from: markdown+smart 16 | highlight-style: haddock 17 | table-of-contents: true 18 | toc-depth: 2 19 | top-level-division: chapter 20 | number-sections: true 21 | reference-location: section 22 | 23 | input-files: 24 | - ../category.tex 25 | - preface.md 26 | - part1/ch01.md 27 | - part1/ch02.md 28 | - part1/ch03.md 29 | - part1/ch04.md 30 | - part1/ch05.md 31 | - part1/ch06.md 32 | - part1/ch07.md 33 | - part1/ch08.md 34 | - part1/ch09.md 35 | - part1/ch10.md 36 | - part2/ch01.md 37 | - part2/ch02.md 38 | - part2/ch03.md 39 | - part2/ch04.md 40 | - part2/ch05.md 41 | - part2/ch06.md 42 | - part3/ch01.md 43 | - part3/ch02.md 44 | - part3/ch03.md 45 | - part3/ch04.md 46 | - part3/ch05.md 47 | - part3/ch06.md 48 | - part3/ch07.md 49 | - part3/ch08.md 50 | - part3/ch09.md 51 | - part3/ch10.md 52 | - part3/ch11.md 53 | - part3/ch12.md 54 | - part3/ch13.md 55 | - part3/ch14.md 56 | - part3/ch15.md 57 | - index_html.md 58 | - acknowledgments.md 59 | - license.md 60 | -------------------------------------------------------------------------------- /english/defaults.yaml: -------------------------------------------------------------------------------- 1 | # pdf 2 | to: latex 3 | pdf-engine: lualatex 4 | metadata: 5 | documentclass: book 6 | variables: 7 | classoption: 8 | - a5paper 9 | include-in-header: 10 | - ../packages.tex 11 | - ../codeblock.tex 12 | - ../frontmatter.tex 13 | 14 | # common 15 | metadata-file: metadata.yaml 16 | from: markdown+smart 17 | highlight-style: ../monochrome-no-underline.theme 18 | table-of-contents: true 19 | toc-depth: 2 20 | top-level-division: chapter 21 | number-sections: true 22 | reference-location: section 23 | 24 | input-files: 25 | - ../category.tex 26 | - preface.md 27 | - ../mainmatter.tex 28 | - part1/ch01.md 29 | - part1/ch02.md 30 | - part1/ch03.md 31 | - part1/ch04.md 32 | - part1/ch05.md 33 | - part1/ch06.md 34 | - part1/ch07.md 35 | - part1/ch08.md 36 | - part1/ch09.md 37 | - part1/ch10.md 38 | - part2/ch01.md 39 | - part2/ch02.md 40 | - part2/ch03.md 41 | - part2/ch04.md 42 | - part2/ch05.md 43 | - part2/ch06.md 44 | - part3/ch01.md 45 | - part3/ch02.md 46 | - part3/ch03.md 47 | - part3/ch04.md 48 | - part3/ch05.md 49 | - part3/ch06.md 50 | - part3/ch07.md 51 | - part3/ch08.md 52 | - part3/ch09.md 53 | - part3/ch10.md 54 | - part3/ch11.md 55 | - part3/ch12.md 56 | - part3/ch13.md 57 | - part3/ch14.md 58 | - part3/ch15.md 59 | - index.md 60 | - acknowledgments.md 61 | - license.md 62 | -------------------------------------------------------------------------------- /japanese/defaults.yaml: -------------------------------------------------------------------------------- 1 | # pdf 2 | to: latex 3 | pdf-engine: lualatex 4 | metadata: 5 | documentclass: jlreq 6 | variables: 7 | classoption: 8 | - book 9 | - paper=a5paper 10 | include-in-header: 11 | - ../packages.tex 12 | - ../codeblock.tex 13 | - style.tex 14 | - ../frontmatter.tex 15 | 16 | # common 17 | metadata-file: metadata.yaml 18 | from: markdown+smart 19 | highlight-style: ../monochrome-no-underline.theme 20 | table-of-contents: true 21 | toc-depth: 2 22 | top-level-division: chapter 23 | number-sections: true 24 | reference-location: section 25 | 26 | input-files: 27 | - ../category.tex 28 | - preface.md 29 | - ../mainmatter.tex 30 | - part1/ch01.md 31 | - part1/ch02.md 32 | - part1/ch03.md 33 | - part1/ch04.md 34 | - part1/ch05.md 35 | - part1/ch06.md 36 | - part1/ch07.md 37 | - part1/ch08.md 38 | - part1/ch09.md 39 | - part1/ch10.md 40 | - part2/ch01.md 41 | - part2/ch02.md 42 | - part2/ch03.md 43 | - part2/ch04.md 44 | - part2/ch05.md 45 | - part2/ch06.md 46 | - part3/ch01.md 47 | - part3/ch02.md 48 | - part3/ch03.md 49 | - part3/ch04.md 50 | - part3/ch05.md 51 | - part3/ch06.md 52 | - part3/ch07.md 53 | - part3/ch08.md 54 | - part3/ch09.md 55 | - part3/ch10.md 56 | - part3/ch11.md 57 | - part3/ch12.md 58 | - part3/ch13.md 59 | - part3/ch14.md 60 | - part3/ch15.md 61 | - index.md 62 | - acknowledgments.md 63 | - license.md 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # milewski-ctfp-markdown 2 | 3 | バルトシュ・ミレフスキー著『プログラマーのための圏論』の非公式markdown版([原著者の公開許可済み](https://github.com/ktgw0316/milewski-ctfp-markdown/issues/2#issuecomment-1494275529)の日本語訳を含む) 4 | 5 | An *unofficial* markdown version of "**C**ategory **T**heory **F**or **P**rogrammers" 6 | by [Bartosz Milewski][bartosz github], based on: 7 | 8 | * Original [blogpost series][blogpost series] 9 | * [PDF/LaTeX version][ctfp-pdf] by Igal Tabachnik 10 | * [epub version][onlurking] by Diogo Felix (base.css) 11 | * [pandoc-toc-sidebar](https://github.com/Mushiyo/pandoc-toc-sidebar) by Mushiyo (pandoc html template) 12 | 13 | ## How to build 14 | 15 | 1. Install [pandoc](https://pandoc.org/installing.html) and LuaLaTeX 16 | 1. `cd english/` (or `cd japanese/` if you want to build Japanese version) 17 | 1. Convert markdown to: 18 | * html: `pandoc -d ../defaults_html.yaml --template=../html_templates/toc-sidebar.html --to=html5 -o index.html` 19 | * epub: `pandoc -d ../defaults_html.yaml --to=epub -o ctfp.epub` 20 | * pdf: `pandoc -d defaults.yaml -o ctfp.pdf` 21 | * If you want to make index available in pdf, you need to run the following commands: 22 | 23 | ```shell 24 | pandoc -d defaults.yaml -o ctfp.tex 25 | sed -i -f ../ensuremath.sed ctfp.tex 26 | lualatex ctfp 27 | upmendex -d index.dic ctfp 28 | lualatex ctfp 29 | ``` 30 | 31 | [bartosz github]: https://github.com/BartoszMilewski 32 | [blogpost series]: 33 | https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/ 34 | [ctfp-pdf]: https://github.com/hmemcpy/milewski-ctfp-pdf/ 35 | [onlurking]: https://github.com/onlurking/category-theory-for-programmers 36 | 37 | ## 日本語訳について 38 | 39 | html版は[github pages](https://ktgw0316.github.io/milewski-ctfp-markdown/)としても公開しています。 40 | 41 | ※2025年3月現在、第2部まで監訳が終わった段階です。誤訳を含む可能性があることにご注意ください。 42 | 43 | * 監訳:松田 一孝 44 | * 翻訳:北川 雅裕 45 | -------------------------------------------------------------------------------- /monochrome-no-underline.theme: -------------------------------------------------------------------------------- 1 | { 2 | "text-color": null, 3 | "background-color": null, 4 | "line-number-color": null, 5 | "line-number-background-color": null, 6 | "text-styles": { 7 | "Alert": { 8 | "text-color": null, 9 | "background-color": null, 10 | "bold": true, 11 | "italic": false, 12 | "underline": false 13 | }, 14 | "Annotation": { 15 | "text-color": null, 16 | "background-color": null, 17 | "bold": false, 18 | "italic": true, 19 | "underline": false 20 | }, 21 | "Comment": { 22 | "text-color": null, 23 | "background-color": null, 24 | "bold": false, 25 | "italic": true, 26 | "underline": false 27 | }, 28 | "CommentVar": { 29 | "text-color": null, 30 | "background-color": null, 31 | "bold": false, 32 | "italic": true, 33 | "underline": false 34 | }, 35 | "ControlFlow": { 36 | "text-color": null, 37 | "background-color": null, 38 | "bold": true, 39 | "italic": false, 40 | "underline": false 41 | }, 42 | "DataType": { 43 | "text-color": null, 44 | "background-color": null, 45 | "bold": false, 46 | "italic": false, 47 | "underline": false 48 | }, 49 | "Documentation": { 50 | "text-color": null, 51 | "background-color": null, 52 | "bold": false, 53 | "italic": true, 54 | "underline": false 55 | }, 56 | "Error": { 57 | "text-color": null, 58 | "background-color": null, 59 | "bold": true, 60 | "italic": false, 61 | "underline": false 62 | }, 63 | "Information": { 64 | "text-color": null, 65 | "background-color": null, 66 | "bold": false, 67 | "italic": true, 68 | "underline": false 69 | }, 70 | "Keyword": { 71 | "text-color": null, 72 | "background-color": null, 73 | "bold": true, 74 | "italic": false, 75 | "underline": false 76 | }, 77 | "Preprocessor": { 78 | "text-color": null, 79 | "background-color": null, 80 | "bold": true, 81 | "italic": false, 82 | "underline": false 83 | }, 84 | "Warning": { 85 | "text-color": null, 86 | "background-color": null, 87 | "bold": false, 88 | "italic": true, 89 | "underline": false 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /base.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import url(fonts/fonts.css); 3 | @namespace epub "http://www.idpf.org/2007/ops"; 4 | 5 | body { 6 | margin: 5%; 7 | font-size: medium; 8 | font-family: serif; 9 | hyphens: auto; 10 | -epub-hyphens: auto; 11 | line-break: strict; 12 | word-break: break-word; 13 | overflow-wrap: break-word; 14 | word-wrap: break-word; 15 | } 16 | 17 | h1, 18 | h2, 19 | h3, 20 | h4, 21 | h5, 22 | h6 { 23 | font-family: sans-serif; 24 | font-variant: small-caps; 25 | hyphens: none; 26 | -epub-hyphens: none; 27 | page-break-after: avoid; 28 | text-align: center; 29 | margin: 1.5em 0; 30 | } 31 | 32 | p { 33 | text-indent: 1em; 34 | } 35 | 36 | header>.title { 37 | font-size: 2.4em; 38 | text-align: center; 39 | } 40 | 41 | header>.author { 42 | font-size: 1.4em; 43 | text-align: right; 44 | } 45 | 46 | h1+p { 47 | text-indent: 0; 48 | } 49 | 50 | section>h1+p:first-letter { 51 | float: left; 52 | font-size: 2.4em; 53 | line-height: 1; 54 | margin-top: 0.1em; 55 | margin-right: 0.1em; 56 | } 57 | 58 | /* 59 | blockquote+p, 60 | blockquote p:first-child, 61 | h2+p, 62 | h3+p, 63 | */ 64 | header+p, 65 | hr+p>ol>li>p:first-child { 66 | text-indent: 0; 67 | } 68 | 69 | ol.toc { 70 | padding: 0; 71 | margin-left: 1em; 72 | } 73 | 74 | ol.toc li { 75 | list-style-type: none; 76 | margin: 0; 77 | padding: 0; 78 | } 79 | 80 | hr { 81 | border: none; 82 | border-top: 1px solid; 83 | height: 0; 84 | margin: 1.5em auto; 85 | width: 25%; 86 | } 87 | 88 | cite { 89 | font-style: normal; 90 | } 91 | 92 | abbr { 93 | border: none; 94 | white-space: nowrap; 95 | } 96 | 97 | blockquote cite { 98 | display: block; 99 | font-style: italic; 100 | text-align: right; 101 | } 102 | 103 | blockquote cite i { 104 | font-style: normal; 105 | } 106 | 107 | a { 108 | hyphens: none; 109 | -epub-hyphens: none; 110 | } 111 | 112 | blockquote p { 113 | font-style: italic; 114 | text-align: left; 115 | text-indent: 0; 116 | } 117 | 118 | blockquote p span { 119 | display: block; 120 | padding-left: 1em; 121 | text-indent: -1em; 122 | } 123 | 124 | blockquote br { 125 | display: none; 126 | } 127 | 128 | h1 { 129 | font-size: 1.8em; 130 | } 131 | 132 | h2 { 133 | font-size: 1.4em; 134 | } 135 | 136 | h3 { 137 | font-size: 1.25em; 138 | } 139 | 140 | pre, 141 | tt, 142 | code, 143 | samp, 144 | kbd { 145 | font-family: "Inconsolata LGC", "DejaVu Sans Mono", monospace; 146 | word-wrap: break-word; 147 | font-size: 0.9em; 148 | } 149 | 150 | pre { 151 | line-height: 1.2em; 152 | margin-left: 1em; 153 | margin-bottom: 1em; 154 | white-space: pre-wrap; 155 | display: block; 156 | } 157 | 158 | img { 159 | display: block; 160 | margin: 0 auto; 161 | border-radius: 0.3em; 162 | -webkit-border-radius: 0.3em; 163 | -webkit-box-shadow: rgba(0, 0, 0, 0.15) 0 1px 4px; 164 | box-shadow: rgba(0, 0, 0, 0.15) 0 1px 4px; 165 | box-sizing: border-box; 166 | border: white 0.5em solid; 167 | } 168 | 169 | figcaption { 170 | font-size: 0.8em; 171 | text-align: center; 172 | } 173 | 174 | p img { 175 | border-radius: 0; 176 | border: none; 177 | } 178 | 179 | div:has(>div.page>svg) { 180 | width: 100% !important; 181 | zoom: 1.3; 182 | column-gap: 0.6em; 183 | } 184 | 185 | div.page>svg { 186 | right: 0; 187 | margin: 0 auto; 188 | } 189 | 190 | sup { 191 | vertical-align: super; 192 | line-height: 0.5em; 193 | } 194 | 195 | sub { 196 | vertical-align: sub; 197 | line-height: 0.5em; 198 | } 199 | 200 | span.keyword { 201 | font-family: sans-serif; 202 | font-weight: bold; 203 | } 204 | -------------------------------------------------------------------------------- /japanese/preface.md: -------------------------------------------------------------------------------- 1 | \clearpage 2 | 3 | # 序文 {-} 4 | 5 | > しばらく前から、プログラマーを対象とした圏論に関する本を書こうと考えていた。計算機科学者ではなくプログラマー、科学者ではなくエンジニア向けだということに注目してほしい。正気の沙汰ではないし、本当に恐ろしい。科学と工学の間に大きなギャップがあるのは否定できないと思う。自分自身がその分断の両側で仕事をしてきたからだ。それでも、物事を説明したいという強い衝動をいつも感じていた。簡潔な説明の達人だったリチャード・ファインマン[^feynman]を心から尊敬している。自分がファインマンではないことは分かっているが、最善を尽くしたい。まずは、この序文――読者に圏論を学ぶ気を起こさせることを想定したもの――を公開することから始めようと思う。それによって議論を開始しフィードバックを募れることを願っている[^video]。 6 | 7 | [^feynman]: 訳注:理論物理学者。量子電磁力学での業績により1965年のノーベル物理学賞を朝永振一郎、ジュリアン・シュウィンガーと共同受賞した。 8 | 9 | [^video]: 著者がこの内容を講義している映像も(またはYouTubeで "bartosz milewski category theory" を検索)で観られる。 10 | 11 | \vskip1\baselineskip 12 | 13 | ここからの数段落をかけて、この本はあなたのために書かれたものであり、数学のうちでも特に抽象的な分野を学ぶために「あり余る自由時間」を費やすことへのどんな反対意見も全く根も葉もないことを確信してもらえるように試みたい。 14 | 15 | 私の楽観論はいくつかの観察に基づいている。第一に、圏論は極めて有用なプログラミングのアイデアの宝庫だ。Haskellプログラマーたちは長い間この資源を利用していて、得られたアイデアは他の言語にゆっくりと浸透してきているが、進行が遅すぎる。もっとスピードを上げる必要がある。 16 | 17 | 第二に、いろいろな種類の数学があり、それぞれ興味を惹く人も異なる。微積分や代数にアレルギーがあったとしても、圏論を楽しめないとは限らない。私としては、圏論はプログラマーのマインドに特に合った数学であるとさえ主張したい。圏論では、個々の物事を扱うのではなく、構造を扱うからだ。圏論はプログラムを合成可能にするような構造を扱う。 18 | 19 | 合成は圏論の最も根本であり、圏そのものの定義の一部だ。そして私は、合成こそプログラミングの本質であると強く主張したい。我々は、偉大なエンジニアがサブルーチンのアイデアを思いつく遥か前から、ずっとものを合成してきた。かつて構造化プログラミングはプログラミングに革命をもたらした。コードのブロックを合成可能にしたからだ。続いてオブジェクト指向プログラミングが登場した。これはオブジェクトを合成することこそすべてだ。関数プログラミングは、関数や代数的データ構造を合成するだけでなく、並行性をも合成可能にする。これは他のプログラミングパラダイムでは事実上不可能だ。 20 | 21 | 第三に、私には秘密兵器の「肉切り包丁」がある。それを使って数学を捌いて、よりプログラマーの口に合うものにするつもりだ。プロの数学者としては、すべての仮定を確かめ、すべての命題を適切に述べ、すべての証明を厳密に構成するために細心の注意を払う必要がある。そのせいで数学の論文や書籍は門外漢には非常に読みにくくなっている。だが、私は物理学者としての教育を受けており、物理学は形式的でない推論を用いて驚くべき進歩を遂げた学問だ。かつて数学者たちはディラックのデルタ関数を嗤った。デルタ関数は偉大な物理学者であるP.A.M. ディラックが微分方程式を解く過程で作ったものだ。数学者たちは、ディラックの洞察を形式化した微積分学の全く新しい分野として超関数理論 (distribuiton theory) を発見したとき、嗤うのをやめた。 22 | 23 | 当然ながら、大雑把に議論するときには明らかに間違ったことを言ってしまう危険があるので、本書では非公式な議論の背景にしっかりした数学的理論があるように気を付けたい。私のベッドサイドには、読み古したソーンダーズ・マックレーンの『圏論の基礎』が置かれている。 24 | 25 | この本は*プログラマーのための*圏論なので、すべての主要な概念を説明するのにコンピューターコードを使うことにしたい。お気付きかもしれないが、より普及している命令型言語よりも関数型言語の方が数学に近い。また、より強力な抽象化能力を提供する。そのため、自然な誘惑として「圏論の恩恵に浴するにはHaskellを学ばなければならない」と言いたくなるかもしれない。しかし、それは圏論が関数プログラミング以外の用途を持たないことを意味しており、全く誤っている。そこで、C++での例を数多く載せようと思う。確かに、いくつかの醜い構文を克服しなければならず、雑然とした背景に紛れてパターンが目立たなくなったり、高度な抽象化の代わりにコピー&ペーストに頼らなければならない場面もあるだろう。だが、それがC++プログラマーというものだ。 26 | 27 | しかし、Haskellに関しては逃れられない。Haskellプログラマーになる必要はないが、C++で実装しようとしているアイデアをスケッチしたり文書化したりするための言語としてHaskellが必要になる。私もそうやってHaskellを始めた。そして、簡潔な構文と強力な型システムが、C++のテンプレート、データ構造、アルゴリズムを理解し実装する上で大きな助けになると気付いた。もっとも、読者がすでにHaskellを知っているとは期待できないので、ゆっくり紹介しながら進行に応じてすべて説明していくつもりだ。 28 | 29 | プログラマーとしての経験が豊富なら、次のように自問するかもしれない。長い間ずっと圏論や関数型の手法を気にすることなくコーディングしてきたが、何が変わったのだろう? 確かにそう思わずにいられないだろうが、関数型の新機能が続々と登場し、命令型言語に侵入していることに気付いてほしい。オブジェクト指向プログラミングの牙城であるJavaでさえ、ラムダを導入した。最近のC++は数年ごとの新しい標準という激動のペースで進化し、変化する世界に追いつこうとしている。これらはすべて、破壊的な変化、すなわち物理学者である我々が相転移と呼ぶものに備えるための動きだ。お湯を温め続けると、やがて沸騰しはじめる。我々はいま、その中のカエルの立場にいる。カエルはどんどん熱くなるお湯の中で泳ぎ続けるべきなのか、それとも何か別のものを探し始めるべきなのか、決めなければならない。 30 | 31 | `\begin{figure}[H] \centering`{=latex} 32 | ![](images/img_1299.jpg){width=50%} 33 | `\end{figure}`{=latex} 34 | 35 | \noindent 36 | 大きな変化を引き起こしている力のひとつがマルチコア革命だ。広く普及しているプログラミングパラダイムであるオブジェクト指向プログラミングは、並行・並列処理の領域では何のメリットもなく、その代わりに危険でバグを生じやすい設計を奨励している。オブジェクト指向の基本的前提であるデータ隠蔽は、データの共有や改変と組み合わされると、データ競合のレシピになる。ミューテックス^[訳注:排他制御機構のひとつ。同時に1つの所有者(スレッドまたはプロセス)だけが共有資源にアクセス可能とする仕組みで、所有者だけがロックを解除できる。] とそれが保護するデータを組み合わせるというアイデアは素晴らしい。しかし、残念ながらロックは合成できないし、ロックを隠すことでデッドロックが発生しやすくなり、デバッグが難しくなる。 37 | 38 | さらに、並行性が存在しないとしても、ソフトウェアシステムの複雑さが増すにつれて、命令型パラダイムのスケーラビリティは限界が試されている。簡単に言うと、副作用が手に負えなくなってきている。確かに、副作用のある関数は便利だし簡単に書ける。それらの作用は、原理的には、名前やコメントに示しておける。SetPasswordやWriteFileなどと命名された関数は、明らかに何らかの状態を変化させ副作用を発生させるが、我々はそれに対処するのには慣れている。副作用のある関数に副作用のある別の関数を合成し始めたときに初めて、物事は複雑になり始める。副作用が本質的に悪いわけではなく、隠れて見えないせいで大規模な管理が不可能になっているのだ。副作用はスケールせず、そして命令型プログラミングでは副作用こそすべてだ。 39 | 40 | ハードウェアの変化とソフトウェアの複雑さが増すことで、プログラミングの基礎を再考する必要に迫られている。ヨーロッパの偉大なゴシック大聖堂の建設者と同じように、我々は材料と構造の限界まで技術を磨き続けてきた。フランスには未完成のゴシック建築の[ボーヴェ大聖堂](https://en.wikipedia.org/wiki/Beauvais_Cathedral)^[] があり、限界との深く人間的なこの闘いの証拠となっている。それまでの高さと軽さの記録をすべて破ることを目論んでいたが、相次ぐ崩壊に見舞われた。鉄筋や木製の支柱などの応急処置で崩壊を防いでいるが、明らかに多くのことがうまくいかなかった。現代の視点から見ると、材料科学、コンピューターモデリング、有限要素解析、そして汎用的な数学と物理学の助けなしに、これほど多くのゴシック構造が成功裏に完成したことは奇跡だ。将来の世代が、複雑なオペレーティングシステム、ウェブサーバー、インターネット基盤を構築する際に我々が示してきたプログラミングのスキルを賞賛するようになるのを願っている。率直に言って、彼らはそうすべきだ。我々はそれらすべてを非常に貧弱な理論的基盤に基づいて行ってきたのだから。前進するためには、これらの基盤を修復しなければならない。 41 | 42 | ![ボーヴェ大聖堂の崩壊を阻止するための応急処置](images/beauvais_interior_supports.jpg "ボーヴェ大聖堂の崩壊を阻止するための応急処置"){width=50%} 43 | -------------------------------------------------------------------------------- /japanese/part3/ch01.md: -------------------------------------------------------------------------------- 1 | \setcounter{part}{2} 2 | \setcounter{chapter}{16} 3 | \part{} 4 | 5 | # 射こそすべて 6 | 7 | まだ圏論の勘所は射だと確信してもらえていないなら、私が務めをきちんと果たせなかったということになる。次章の話題である随伴 (adjunction) は、hom集合間の同型によって定義されるため、hom集合の構成要素についての直観を見直すのが理にかなっている。また、随伴はこれまで見てきた多くの構成を記述するさらに汎用的な語彙を提供するため、それらの構成を復習しておくのも有意義だろう。 8 | 9 | ## 関手 10 | 11 | まず始めに、関手を射の写像だと真剣に考えるべきだ。これはHaskellの`Functor`型クラスの定義において強調される考え方だ。そこでは`fmap`が中心だった。もちろん、関手は対象――射の両端――も写す。そうでなければ、合成の保存について語れない。対象は射のどのペアが合成可能か教えてくれる。一方の射の終点がもう一方の始点と等しくなければ合成できない。したがって、射の合成を[*持ち上げられた*]{.keyword #lifted}\index{持ち上げられた}射の合成に写すなら、それらの両端の写像もほぼ決まる。 12 | 13 | ## 可換図式 14 | 15 | 射についての性質の多くは可換図式によって表される。ある特定の射が他の射の合成として複数の方法で記述できるなら、可換図式があることになる。 16 | 17 | 特に、可換図式はほぼすべての普遍的構成の基礎となっている(始対象と終対象という重要な例外はある)。このことはすでに、積、余積、その他さまざまな(余)極限、冪対象、自由モノイドなどの定義で見てきた。 18 | 19 | 積は普遍的構成の簡単な例だ。2つの対象$a$と$b$を選び、それらの積となる普遍性を持つような、射$p$と$q$のペアを伴う対象$c$が存在するかを見る。 20 | 21 | `\begin{figure}[H] \centering`{=latex} 22 | ![](images/productranking.jpg){width=30%} 23 | `\end{figure}`{=latex} 24 | 25 | \noindent 26 | 積は極限の特別な場合でもある。極限は錐によって定義される。一般的な錐は可換図式から作成される。それらの図式の可換性は、関手間の写像についての適切な自然性条件で置き換えられる^[訳注:錐とは$\Nat(\Delta_c, F)$ のことだったのを思い出してほしい。]。このようにして、可換性は自然変換という高水準言語に対するアセンブリー言語の役割に降格される。 27 | 28 | ## 自然変換 29 | 30 | 一般に、自然変換は射から可換正方図式への写像が必要なときに非常に便利だ。自然性の正方図式で向かい合う辺のうち2つは、ある射$f$を2つの関手$F$と$G$でそれぞれ写したものだ。残りの2辺は自然変換の成分(これらも射)である。 31 | 32 | `\begin{figure}[H] \centering`{=latex} 33 | ![](images/3_naturality.jpg){width=35%} 34 | `\end{figure}`{=latex} 35 | 36 | \noindent 37 | 自然性は「隣接する」(つまり射でつながった)成分に移っても圏や関手の構造に反しないことを意味している。自然変換の成分を使って対象間のギャップをまず埋めてから関手を使って隣の対象にジャンプするのでも、その逆でも関係ない。すなわち、2つの方向は直交している。いうなれば、自然変換は左右に移動させ、関手は上下や前後に移動させる。関手の*像*は、その行き先となる圏でのシートとして視覚化できる。この見方では、自然変換は$F$に対応するシートを$G$に対応する別のシートに写す。 38 | 39 | `\begin{figure}[H] \centering`{=latex} 40 | ![](images/sheets.png){width=35%} 41 | `\end{figure}`{=latex} 42 | 43 | \noindent 44 | この直交性のHaskellにおける例はすでに見ている。そこでは、関手の作用はコンテナーの形状を変更せずに内容を変更し、一方で自然変換は内容を変更せずに別のコンテナーに詰め直すものだった^[訳注:詰め直す際に各要素の位置が変わり得ることを考えると、位置に依存しないような変更である必要がある。]。これらの操作の順序は関係なかった。 45 | 46 | 極限の定義の中で錐が自然変換に置き換えられるのを見た。自然性はすべての錐の側面が可換だと保証する。しかし、極限は錐の*間の*写像によって定義されていた。これらの写像は可換性条件も満たす必要があった。(たとえば、積の定義における三角形は可換である必要がある。) 47 | 48 | これらの条件も自然性によって置き換えられる。*普遍な*錐、すなわち極限が、(反変)hom関手 49 | $$F \Colon c \to \cat{C}(c, \Lim{D})$$ 50 | と、$\cat{C}$内の対象を、それ自体が自然変換である錐に写すような(反変)関手 51 | $$G \Colon c \to \Nat(\Delta_c, D)$$ 52 | の自然変換として定義されていたのを思い出してほしい。ここで、$\Delta_c$は定関手、$D$は$\cat{C}$での図式を定義する関手である。関手$F$と$G$は両方とも、$\cat{C}$の射に対する作用が明確に定義されている。奇遇にも$F$と$G$の間の特定の自然変換は*同型*である。 53 | 54 | ## 自然同型 55 | 56 | 自然同型――すべての成分が可逆な自然変換――は、圏論で「2つのものは同じである」と言うときの言い方だ。そのような変換の成分は対象間の同型射――逆が存在する射――でなければならない。関手の像をシートとして表すなら、自然同型はシート間の1対1の可逆な写像だと言える。 57 | 58 | ## Hom集合 59 | 60 | それにしても、射とは何だろう? 射は対象よりも構造が豊かだ。対象とは違って、射には2つの端がある。しかし、始点となる対象と終点となる対象を固定すると、それら2つの間の射たちは(少なくとも局所的に小さい圏では)単に集合をなしてしまう。この集合の要素を区別するために$f$や$g$のような名前を付けることはできるが、一体何がこれらの射を区別しているのだろう? 61 | 62 | 与えられたhom集合内の射同士の本質的な差異は、(隣接するhom集合からの)他の射とどのように合成されるかにある。$f$との合成(前合成でも後合成でもよい)が$g$との合成と異なるような射$h$が存在する場合、つまり、たとえば 63 | $$h \circ f \neq h \circ g$$ 64 | なら$f$と$g$の違いを直接「観察」できる。しかし、違いが直接観察できない場合でも、関手を使えばそのhom集合にズームインできる。関手$F$は2本の射を、より豊かな圏における別々の射 65 | $$F f \neq F g$$ 66 | に写せる。そこでは、隣接するhom集合による分解能がより高い場合がある。たとえば、$F$の像に含まれない$h'$によって 67 | $$h' \circ F f \neq h' \circ F g$$ 68 | のように区別できる場合がある^[訳注:合成後の両辺の射を結局どう区別するのかが述べられていないが、根底には「2本の射のうち一方が恒等射で他方がその他の自己射となるような合成が見つかるならば、それらは区別できる」というアイデアがある。著者のブログでのコメントを参照。]。 69 | 70 | ## Hom集合同型 71 | 72 | 圏論では多くの構成がhom集合間の同型に依存している。もっとも、hom集合はただの集合なので、それらの間の同型から分かることはあまりない。有限集合の場合は、同型は要素数が同じだと示すだけだ。無限集合の場合は、同型が存在するならばそれらの濃度が同じでなければならない。しかし、hom集合の意味のある同型はすべて、合成も考慮しなければならない。合成に関わるhom集合はひとつだけではない。あらゆるhom集合にまたがる同型を定義する必要があり、合成と相互運用できるような何らかの互換性の条件を課す必要がある。そして、[*自然*]{.keyword #natural}\index{自然}同型はその条件にぴったり合う。 73 | 74 | だが、hom集合同士の自然同型とは何だろう? 自然性は、関手間の写像の性質であり、集合間の写像についてのものではない。つまり、いま話しているのは実際にはhom集合値関手の間の自然同型についてである。それらの関手は単なる集合値関手ではない。射に対するその作用は、適切なhom関手によって導かれる。射はhom関手によって、(合成の変性に依存して)前合成か後合成のどちらかで正準的に写される。 75 | 76 | 米田埋め込みはそのような同型の一例だ。それは$\cat{C}$内のhom集合を関手圏内のhom集合に写す。そしてそれは自然だ。米田埋め込みにおける関手のひとつは$\cat{C}$のhom関手で、もうひとつは対象をhom集合間の自然変換の集合に写すような関手だ。 77 | 78 | 極限の定義もhom集合間の自然同型だ(ここでも2番目は関手圏内のhom集合だ)。 79 | $$\cat{C}(c, \Lim{D}) \simeq \Nat(\Delta_c, D)$$ 80 | 実は、冪対象や自由モノイドの構成もhom集合間の自然同型として書き直せる。 81 | 82 | これは偶然の一致ではない――次章で見るように、これらはhom集合の自然同型として定義される随伴のさまざまな例にすぎない。 83 | 84 | ## Hom集合の非対称性 85 | 86 | 随伴を理解するのに役立つ観察結果はもう1つある。Hom集合は一般に対称ではない。Hom集合$\cat{C}(a, b)$ は、hom集合$\cat{C}(b, a)$ と大きく異なることがよくある。この非対称性の究極の例は、半順序を圏と見なすことだ。半順序では、$a$が$b$以下の場合、かつその場合に限って$a$から$b$への射が存在する。さらに$a$と$b$が異なる場合は、$b$から$a$へと逆方向に進む射は存在しない。Hom集合$\cat{C}(a, b)$ が空集合でない(ここでは単元集合であることを意味する)なら、$a = b$でない限り、$\cat{C}(b, a)$ は空でなければならない。この圏の射には明確な一方向の流れが存在する。 87 | 88 | 関係が反対称でなくてもよい前順序も、たまにある循環を除けば「ほとんど」方向付けられている。任意の圏を前順序の一般化と見なすと便利だ。 89 | 90 | 前順序は細い圏だ――すべてのhom集合が単元集合か空集合のどちらかだ。一般の圏は「太い」(thick) 前順序として描写できる。 91 | 92 | ## 課題 93 | 94 | 1. 退化 (degenerate) した自然性条件の例を考え、適切な図を描け。たとえば、関手$F$または$G$のどちらかが対象$a$と$b$($f \Colon a \to b$の両端)の両方を同じ対象に、$F a = F b$または$G a = G b$のように写したらどうなるか? (この方法で錐や余錐が得られることに注目してほしい。)次に、$F a = G a$または$F b = G b$のどちらかの場合について考えよ。最後に、自分自身へループする射$f \Colon a \to a$から始めた場合はどうか? 95 | -------------------------------------------------------------------------------- /japanese/part2/ch01.md: -------------------------------------------------------------------------------- 1 | \setcounter{part}{1} 2 | \setcounter{chapter}{10} 3 | \part{} 4 | 5 | # 宣言的プログラミング 6 | 7 | 第I部では、圏論とプログラミングはどちらも合成可能性に関するものだと論じた。プログラミングでは、扱える程度の詳細さに達するまで問題を分解し続け、それぞれの部分問題を順番に解決し、それらの解決策をボトムアップで再合成する。これには大きく2つの方法がある。コンピューターに何をすべきか指示する方法と、どのようにすべきか指示する方法だ。前者は宣言的と呼ばれ、後者は命令的と呼ばれる。 8 | 9 | このことは最も基本的なレベルでさえ見られる。合成自体は宣言的にも定義できる。たとえば、`h`は`g`を`f`の後に合成したものだ。 10 | 11 | ```haskell 12 | h = g . f 13 | ``` 14 | 15 | \noindent 16 | あるいは、命令的にも定義できる。まず`f`を呼び出し、その呼び出しの結果を記憶し、それからその結果を使って`g`を呼び出す。 17 | 18 | ```haskell 19 | h x = let y = f x 20 | in g y 21 | ``` 22 | 23 | \noindent 24 | 命令的な方のプログラムは通常、動作を時系列で並べたものとして記述される。特に、`f`の実行が完了する前に`g`の呼び出しは起こりえない。少なくとも、概念としてはそうだ。ただし、*call-by-need*で引数が渡される遅延評価言語では、実際の実行順序は異なり得る。 25 | 26 | 実際、コンパイラーの賢さによっては、宣言的コードと命令的コードの実行方法にほとんど違いがない場合もある。しかし、この2つの方法論は、問題解決へのアプローチ方法や実装コードの保守性とテスト可能性において、ときには劇的に異なる。 27 | 28 | 最大の疑問はこうだ。問題に直面したとき、解決のための選択肢として、宣言的アプローチと命令的アプローチの両方が常にあるのだろうか? そして、宣言的な解決策があるなら、それは常にコンピューターコードに翻訳できるのだろうか? この疑問への答えは自明とは全く言えず、もしその答えを見つけられたなら、宇宙の理解に革命が起こるだろう。 29 | 30 | 詳しく説明させてほしい。物理学にも似たような双対性がある。それは、何か深い基本原理を指し示したり、我々の心の働きについて何かを教えてくれたりする。リチャード・ファインマンはこの双対性について、自身の量子電磁力学の研究におけるインスピレーションとして言及している。 31 | 32 | ほとんどの物理法則には2つの表現形式がある。1つは局所的すなわち無限小的な考察を用いる。我々はごく近傍の系の状態を見て、それが次の瞬間にどう変化するかを予測する。これは通常、ある期間にわたって積分すなわち合計する必要があるような微分方程式で表される。 33 | 34 | このアプローチが命令的思考に似ていることに注目してほしい。つまり、前のステップの結果に応じた一連の小さなステップに従って最終的な解に到達する。実際、物理系のコンピューターシミュレーションの実装では、微分方程式を差分方程式に変換して反復実行するのが常道だ。小惑星ゲームの宇宙船はそのようにしてアニメーション化される。各時間ステップにおける宇宙船の位置は、速度に時間間隔を掛け算した小さな増分を加えることで変化する。同様に、速度は加速度(力を質量で割った値となる)に比例した小さな増分によって変化する。 35 | 36 | `\begin{figure}[H] \centering`{=latex} 37 | ![](images/asteroids.png){width=50%} 38 | `\end{figure}`{=latex} 39 | 40 | \noindent 41 | ニュートンの運動法則に対応する微分方程式を直接的に記述すると次のようになる。 42 | $$ 43 | \begin{aligned} 44 | F &= m \frac{\mathrm{d}v}{\mathrm{d}t} \\ 45 | v &= \frac{\mathrm{d}x}{\mathrm{d}t} 46 | \end{aligned} 47 | $$ 48 | 同様の方法は、より複雑な問題にも適用できる。たとえば、電磁場の伝播はマクスウェル方程式で記述でき、陽子内部のクォークやグルーオンの挙動さえも格子量子色力学で記述できる。 49 | 50 | この局所的な考え方と、デジタルコンピューターの使用によって促進された空間と時間の離散化とが組み合わさった最たるものは、宇宙全体の複雑さをセルオートマトンの系に縮約しようとするスティーブン・ウルフラム^[訳注:複雑系を専門とする数理物理学者で、数式処理ソフトMathematicaの作者としても知られる。]の英雄的な試みの中に表れている。 51 | 52 | もう1つのアプローチは大域的なものだ。我々はシステムの初期状態と最終状態を見て、それらを結ぶ軌道を、特定の汎関数を最小化することで計算する。最も簡単な例はフェルマーの最小時間の原理だ。それは、光線は伝搬時間が最小となる経路に沿って伝搬すると述べている。特に、反射や屈折をする物体がない場合、点$A$から点$B$への光線は最短経路である直線を通る。しかし、水やガラスのような(透明な)高密度の媒質中では光の伝播速度は遅くなる。したがって、始点を空気中とし、終点を水中とすると、光にとって空中をより長く進んでから水中を近道する方が有利になる。最小時間の経路では光線が空気と水の境界で屈折し、スネルの屈折の法則が導かれる。 53 | $$\frac{\sin\theta_1}{\sin\theta_2} = \frac{v_1}{v_2}$$ 54 | ここで、$v_1$は空気中の光速、$v_2$は水中の光速だ。 55 | 56 | `\begin{figure}[H] \centering`{=latex} 57 | ![](images/snell.jpg){width=30%} 58 | `\end{figure}`{=latex} 59 | 60 | \noindent 61 | 古典力学のすべては最小作用の原理から導出できる。作用は任意の経路について、運動エネルギーからポテンシャルエネルギーを引いた差であるラグランジアンを積分することで計算できる(注:和ではなく差だ――和は全エネルギーとなる)。大砲を撃って標的に命中させようとするとき、弾はまず重力によるポテンシャルエネルギーがより高い場所へと上昇し、しばらくの間そこで作用への負の寄与を蓄積する。しかも、放物線の頂点に向けて減速することで運動エネルギーを最小限に抑える。それから加速することでポテンシャルエネルギーの低い領域を素早く通過する。 62 | 63 | `\begin{figure}[H] \centering`{=latex} 64 | ![](images/mortar.jpg){width=35%} 65 | `\end{figure}`{=latex} 66 | 67 | \noindent 68 | ファインマンの最大の功績は、最小作用の原理が量子力学に一般化できると示したことだ。ここでも、問題は初期状態と最終状態について定式化されている。ファインマン経路積分をそれらの状態間に用いると、遷移確率を計算できる。 69 | 70 | `\begin{figure}[H] \centering`{=latex} 71 | ![](images/feynman.jpg){width=35%} 72 | `\end{figure}`{=latex} 73 | 74 | \noindent 75 | 重要なのは、我々が物理法則を記述できる方法には奇妙で説明のつかない双対性があるということだ。局所的な描像を採用し、物事が連続して小さな増分で起こると捉えてもよい。あるいは、大域的な描像を採用し、初期条件と最終条件を宣言し、途中のすべてはそれらにただ従うと捉えてもよい。 76 | 77 | 大域的アプローチはプログラミングでも使える。たとえば、レイトレーシングを実装する場合などだ。眼の位置と光源の位置を宣言し、それらを光線が接続できる経路を見つければよい。各光線について飛行時間を明示的には最小化しないが、実際にスネルの法則と反射の幾何学を用いて同じ効果を得ている。 78 | 79 | 局所的アプローチと大域的アプローチの大きな違いは、空間の扱いと、さらに重要なことに、時間の扱いだ。局所的なアプローチでは、いま・ここの即時的な満足を受け入れるのに対し、大域的なアプローチでは、あたかも未来があらかじめ決まっていて、我々は不変なる宇宙の性質をただ分析しているかのように、長期的で静的な見方をする。 80 | 81 | ユーザーインタラクションに対する関数型リアクティブプログラミング (FRP) アプローチほど、これが分かりやすく説明されているものはない。想定されるすべてのユーザーアクションに対して個別のハンドラーを記述して、そのすべてが共有の可変状態にアクセスできるようにする代わりに、FRPでは外部イベントを無限リストとして扱って一連の変換を適用する。概念的には、将来のすべてのアクションのリストがそこにあり、プログラムへの入力データとして利用できる。プログラムの観点からは、$\pi$の数字のリスト、擬似乱数のリスト、コンピューターのハードウェアから得られるマウス座標のリストの間に違いはない。いずれの場合も、第$n$項を得るには最初の$n-1$個の項を先に調べる必要がある。時間的イベントについて述べる場合、この性質は*因果律* (causality) と呼ばれる。 82 | 83 | それで、圏論と何の関係があるのだろうか? 私の主張としては、圏論は大域的アプローチを奨励しており、それゆえ宣言的プログラミングを支持している。第一に、微積分とは違って、距離・近傍・時間などの概念が組み込まれていない。あるのは抽象的な対象たちとそれらの間の抽象的な接続だけだ。$A$から$B$へ一連のステップで到達できるなら、一足飛びにも到達できる。さらに、圏論の主要なツールはまさに普遍的構成であり、それは大域的アプローチの典型だ。実際の使用例は、たとえば、圏論的な積の定義ですでに見た。それは積の性質を指定することによってなされた、まさしく宣言的なアプローチだ。積とは2本の射影を伴う対象であり、そういった対象のうち最も優れたものだ。つまり、ある特性を最適化している。それは、他の同様の対象の射影を分解する特性だ。 84 | 85 | `\begin{figure}[H] \centering`{=latex} 86 | ![](images/productranking.jpg){width=35%} 87 | `\end{figure}`{=latex} 88 | 89 | \noindent 90 | これをフェルマーの最短時間の原理、あるいは最小作用の原理と比較してほしい。 91 | 92 | 逆に、デカルト積の従来の定義と対比させるとどうだろう。後者の方がはるかに命令的だ。積の要素を作るには、ある集合から1つの要素を選択し、別の集合から別の要素を選択する、という説明になる。これはペアを作るためのレシピだ。また、ペアを分解するためのレシピもある。 93 | 94 | Haskellなどの関数型言語を含め、ほとんどすべてのプログラム言語では、直積型・余積型・関数型は組み込まれており、普遍的構成で定義されるのではない。ただし、圏論的プログラム言語の作成も試みられている (たとえば、[萩野達也の博士論文](http://web.sfc.keio.ac.jp/~hagino/thesis.pdf)^[]を参照)。 95 | 96 | 直接使われるかどうかにかかわらず、圏論的な定義は既存のプログラミング構成を正当なものにするとともに、新しい構成を生み出す。最も重要なのは、宣言的レベルでコンピュータープログラムについて推論するためのメタ言語を圏論が提供することだ。また、コードとして表す前に問題の仕様について推論することも奨励する。 97 | -------------------------------------------------------------------------------- /html_templates/toc-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | $for(author-meta)$ 11 | 12 | $endfor$ 13 | $if(date-meta)$ 14 | 15 | $endif$ 16 | $if(keywords)$ 17 | 18 | $endif$ 19 | 20 | $if(title-prefix)$$title-prefix$ – $endif$$pagetitle$ 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 37 | $if(toc)$ 38 | 39 | $endif$ 40 | $if(quotes)$ 41 | 42 | $endif$ 43 | $if(highlighting-css)$ 44 | 47 | $endif$ 48 | $for(css)$ 49 | 50 | $endfor$ 51 | $if(math)$ 52 | $math$ 53 | $endif$ 54 | 55 | $for(header-includes)$ 56 | $header-includes$ 57 | $endfor$ 58 | 59 | 60 | 61 | $for(include-before)$ 62 | $include-before$ 63 | $endfor$ 64 | 65 | 85 | 86 |
87 |
88 | $if(toc)$ 89 | 95 |
96 | $else$ 97 |
98 | $endif$ 99 | 100 | $body$ 101 |
102 |
103 |
104 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 129 | 130 | $for(include-after)$ 131 | $include-after$ 132 | $endfor$ 133 | 134 | 135 | -------------------------------------------------------------------------------- /japanese/part3/ch03.md: -------------------------------------------------------------------------------- 1 | # 自由/忘却随伴 {#freeforgetful-adjunctions} 2 | 3 | 4 | 5 | 自由構成は随伴の強力な応用例だ。[*自由関手*]{.keyword #free_functor}\index{自由関手}は[*忘却関手*]{.keyword #forgetful_functor2}\index{忘却関手}への左随伴として定義される。忘却関手は構造を忘れる関手で、通常は非常に単純だ。たとえば、多くの興味深い圏は集合の上に構築されている。しかし、それらの集合を抽象化した圏論的な対象は、内部構造 6 | すなわち要素を持たない。それでも、これらの対象が、その圏$\cat{C}$から$\Set$への写像――つまり、関手――が存在するという意味で集合の記憶を保っていることはよくある。$\cat{C}$内のある対象に対応する集合は、その対象の[*台集合*]{.keyword #underlying_set}\index{台集合}と呼ばれる。 7 | 8 | モノイドはそのような台集合――要素の集合――を持つような対象である。モノイドの圏$\cat{Mon}$から集合の圏への忘却関手$U$が存在し、モノイドをその台集合に写す。また、モノイド射(準同型)を集合間の関数に写す。 9 | 10 | 私は$\cat{Mon}$を二重人格だと見なすのが好きだ。一方では、それは乗算と単位元を持つたくさんの集合からなる。他方では、それは特徴のない対象たちからなる圏であり、その唯一の構造は対象間の射として表されている。乗算と単位元を保存するすべての集合関数は$\cat{Mon}$の射となる。\ 11 | \ 12 | 注意事項: 13 | 14 | * 同じ集合に写されるモノイドは多数存在し得る。 15 | * モノイド射は、それらの台集合の間に存在する関数より少ない(あるいは、高々同数)。 16 | 17 | この忘却関手$U$の左随伴である関手$F$は、生成元の集合から自由モノイドを構築するような自由関手となる。この随伴は、前に議論した[自由モノイドの普遍的構成](#free-monoids)(第13章2節)から導かれる。 18 | 19 | ![モノイド$m_1$と$m_2$は同じ台集合を持つ。$m_2$と$m_3$の台集合の間の関数は、それらの間の射よりも多い。](images/forgetful.jpg "モノイド$m_1$と$m_2$は同じ台集合を持つ。$m_2$と$m_3$の台集合の間の関数は、それらの間の射よりも多い。"){width=60%} 20 | 21 | \noindent 22 | Hom集合による定義では、この随伴は次のように書ける。 23 | $$\cat{Mon}(F x, m) \cong \Set(x, U m)$$ 24 | この($x$と$m$について自然な)同型によって以下のことが分かる。 25 | 26 | * $x$によって生成された自由モノイド$F x$と任意のモノイド$m$との間のどのモノイド準同型についても、生成元の集合$x$を$m$の台集合に埋め込む関数が一意に存在する。これは$\Set(x, U m)$ 内の関数である。 27 | * ある$m$の台集合に$x$を埋め込むどの関数についても、$x$によって生成された自由モノイドとそのモノイド$m$の間に一意なモノイド射が存在する。(これは普遍的構成で$h$と呼んでいた射だ。) 28 | 29 | `\begin{figure}[H] \centering`{=latex} 30 | ![](images/freemonadjunction.jpg){width=80%} 31 | `\end{figure}`{=latex} 32 | 33 | \noindent 34 | 直観的には、$F x$は$x$に基づいて構築できる「最大の」モノイドとなる。もしモノイドの内部を見られたなら、$\cat{Mon}(F x, m)$ に属するどの射もこの自由モノイドを別のモノイド$m$に*埋め込む*ことが分かるだろう。その際、いくつかの要素は同一視され得る。特に、その射は$F x$の生成元(すなわち$x$の要素)を$m$に埋め込む。この随伴は、$x$の埋め込み(図の右側の$\Set(x, U m)$ から取ってきた関数によって与えられる)が、左側のモノイドの埋め込みを一意に決定し、またその逆も成り立つことを表している。 35 | 36 | Haskellにおいては、リストデータ構造は自由モノイドである(ただし、注意点がいくつかある。[Dan Doelのブログ記事](http://comonad.com/reader/2015/free-monoids-in-haskell/)[^doel]を参照)。リスト型`[a]`は型`a`が生成元の集合を表しているような自由モノイドである。たとえば、型`[Char]`は、単位元――空リスト`[]`――と、`['a']`、`['b']`などのような単要素リスト――自由モノイドの生成元を含む。残りの要素は「積」を適用することにより生成される。ここでは、2つのリストの積は単に片方をもう片方に連接するだけだ。連接は結合的で単位元的 (unital) だ(つまり、中立元が存在する――ここでは空リストだ)。`Char`によって生成される自由モノイドは、`Char`の文字からなるすべての文字列の集合に他ならない。これはHaskellでは`String`と呼ばれる。 37 | 38 | [^doel]: 39 | 40 | 訳注:要は$\bot$や無限リストを無視すればということ。 41 | 42 | ```haskell 43 | type String = [Char] 44 | ``` 45 | 46 | \noindent 47 | (`type`は型シノニム――既存の型に対する別名――を定義する。) 48 | 49 | もう1つの興味深い例として、単一の生成元から作られた自由モノイドが挙げられる。これはunitのリストの型`[()]`だ。その要素は`[]`、`[()]`、`[(), ()]`などだ。そのようなリストはすべて、1つの自然数――長さによって表せる。それ以外にunitのリストが含む情報はない。このようなリストを2つ連接すると、もとのリストの長さを合計した長さの新しいリストが生成される。型`[()]`が(0を含む)自然数の加算モノイドと同型であることは容易に理解できる。以下の2つの関数は互いに逆であり、この同型の証拠となっている。 50 | 51 | ```haskell 52 | toNat :: [()] -> Int 53 | toNat = length 54 | 55 | toLst :: Int -> [()] 56 | toLst n = replicate n () 57 | ``` 58 | 59 | \noindent 60 | 簡単のため`Natural`型ではなく`Int`型を使ったが、考え方は同じだ^[訳注:`Int`型は固定幅かつ負数も表現可能。`Natural`を使う場合は`length`と`replicate`の代わりに`genericLength`と`genericReplicate`を使う。]。関数`replicate`は、任意の値――ここではunit――で埋められた長さ`n`のリストを作成する。 61 | 62 | ## いくつかの直観 63 | 64 | 以下では、大雑把な議論をいくつか挙げる。この種の議論はまったく厳密ではないが、直観を形成するのには役立つ。 65 | 66 | 自由/忘却随伴について何らかの直観を得るには、関手や関数は本質的に情報を損失するものだということを心に留めておくのがよい。関手は複数の対象や射を潰すことがあり、関数は集合の複数の要素をまとめることがある。また、関手や関数の像は余域の一部しかカバーしていないこともある。 67 | 68 | $\Set$内の「平均的な」hom集合は、最も損失の少ない関数(たとえば単射、または場合によっては同型)から、域全体を単一要素(もしあれば)に潰す定数関数まで、一連の関数すべてを含む。 69 | 70 | 私はよく、任意の圏における射も損失があると見なす。これはメンタルモデルにすぎないが、有用な考え方であり、随伴――特に、圏の1つが$\Set$である場合――について考えるとき役に立つ。 71 | 72 | 形式的には、我々が語れるのは可逆な射(同型射)または非可逆な射についてだけだ。損失があると見なせるのは後者だ。また、単射関数(潰さない関数)と全射関数(余域全体をカバーする関数)という概念を一般化した、モノ (mono-) 射とエピ (epi-) 射という概念もある。ただし、モノかつエピでありながら非可逆な射も存在する場合がある。 73 | 74 | 自由$\dashv$忘却随伴では、左側に制約の多い圏$\cat{C}$があり、右側に制約の少ない圏$\cat{D}$がある。$\cat{C}$の射が「より少ない」のは、何らかの追加構造を保存しなければならないからだ。$\cat{Mon}$の場合は乗算と単位元を保存しなければならない。$\cat{D}$の射はそれほど多くの構造を保存しなくてよいので、「より多くの」射がある。 75 | 76 | 忘却関手$U$を$\cat{C}$内の対象$c$に適用するとき、$c$の「内部構造」を暴いていると見なせる。実際、$\cat{D}$が$\Set$なら、$U$は$c$の内部構造――台集合――を*定義*していると見なせる。(任意の圏においては、対象の内部については他の対象との接続を通じてしか述べられないが、ここでは単に大雑把に議論しているだけだ。) 77 | 78 | $U$を使って2つの対象$c'$と$c$を写す場合、一般に、hom集合$\cat{C}(c', c)$ の写像は$\cat{D}(U c', U c)$ の部分集合のみをカバーすると予想される。$\cat{C}(c', c)$ 内の射が追加構造を保存しなければならないのに対して、$\cat{D}(U c', U c)$ の射はそうではないからだ。 79 | 80 | `\begin{figure}[H] \centering`{=latex} 81 | ![](images/forgettingmorphisms.jpg){width=45%} 82 | `\end{figure}`{=latex} 83 | 84 | \noindent 85 | しかし、随伴は特定のhom集合間の[*同型*]{.keyword #isomorphism}\index{同型}として定義されるので、$c'$は非常に慎重に選択しなければならない。随伴では、$c'$は$\cat{C}$内のどこから選択してもよいわけではなく、自由関手$F$の(より小さいと推察される)像から選択される。 86 | $$\cat{C}(F d, c) \cong \cat{D}(d, U c)$$ 87 | したがって、$F$の像は任意の$c$に向かう多くの射を持つ対象たちのみからなっていなければならない。実際、構造を保存する$F d$から$c$への射は、構造を保存しない$d$から$U c$への射と同数存在する必要がある。これは、$F$の像が(射が保存すべき構造がなくなる程度に)本質的に構造のない対象たちからなっている必要があることを意味する。そのような「構造のない」対象は自由対象 (free object) と呼ばれる。 88 | 89 | `\begin{figure}[H] \centering`{=latex} 90 | ![](images/freeimage.jpg){width=45%} 91 | `\end{figure}`{=latex} 92 | 93 | \noindent 94 | モノイドの例では、自由モノイドは単位律と結合律によって生成される構造以外には何の構造も持たない。それ以外では、すべての乗算は全く新しい要素を生成する。 95 | 96 | 自由モノイドでは、$2 * 3$は$6$ではない――新しい要素${[}2, 3{]}$だ。${[}2, 3{]}$と$6$は同一視されないので、この自由モノイドから他の任意のモノイド$m$への射は、それらを別々に写すことが許される。もちろん、${[}2, 3{]}$と$6$(それらの積)の両方を$m$の同じ要素に写しても構わない。また、加算モノイドで${[}2, 3{]}$と$5$(それらの和)を同一視することなども同様だ。同一視が異なれば、得られるモノイドも異なる。 97 | 98 | これは別の興味深い直観を導く。すなわち、自由モノイドは、モノイドの演算を実行する代わりに、渡された引数を累積 (accumulate) する。たとえば、$2$と$3$を掛ける代わりに、$2$と$3$をリストに記憶する。この手法の利点は、どんなモノイドの演算を使うか指定する必要がないことだ。引数を累積し続けて、最後にだけ演算子を累積結果に適用すればよい。しかも、どんな演算子を適用するかはその最後の時点で選択できる。数値を加算したり、乗算したり、モジュロ2加算したりできる。つまり、自由モノイドは式の作成と評価を分離する。この考え方は代数について述べるときにもう一度見ることになるだろう。 99 | 100 | この直観は他のもっと複雑な自由構成にも一般化できる。たとえば、式木 (expression tree) を評価する前にその全体を累積できる。このアプローチの利点は、そのような木を変換して、評価を高速にしたり、メモリー消費を減らしたりできることだ。これは、たとえば行列計算の実装に使われる。愚直に前から計算すると、中間結果を保存するための一時的な配列が大量に割り当てられる場合があるからだ^[監訳注:Bird & Gibbons: Algorithm Design with Haskell, Cambridge University Press, 2020. 101 | 102 | の14章 "Optimum Bracketing" を参照。]。 103 | 104 | ## 課題 105 | 106 | 1. ある単元集合から生成された自由モノイドを考える。その自由モノイドから任意のモノイド$m$への射と、その単元集合から$m$の台集合への関数との間に1対1の対応があることを示せ。 107 | -------------------------------------------------------------------------------- /japanese/part3/ch13.md: -------------------------------------------------------------------------------- 1 | # トポス 2 | 3 | 思えば、プログラミングから離れてハードコアな数学に飛び込んでしまったかもしれない。だが、プログラミングにおける次の大きな革命が何をもたらすのか、理解のためにどんな数学が必要となるのかは、知り得ないのではないだろうか。すでにいくつか非常に興味深いアイデアが広まりつつある。連続時間^[訳注:離散時間(飛び飛びの時刻値のみを扱う)ではないという意味。]を扱う関数型リアクティブプログラミング、Haskellの型システムの依存型による拡張、ホモトピー型理論のプログラミングにおける探究などだ。 4 | 5 | ここまでは、値の*集合*を使って気楽に型を区別してきた。これは厳密には正しくない。なぜなら、このようなアプローチはある事実を考慮していないからだ。それは、プログラミングでは値を*計算*し、そして計算は時間のかかるプロセスであり、極端な場合には停止しない可能性がある、という事実だ。停止しない計算はどのチューリング完全な言語にも含まれる。 6 | 7 | また、集合論には、計算機科学の基礎として、そして数学自体の基礎としてさえも、最適とは言い難い根本的な理由がある。良い類推としては、集合論は特定のアーキテクチャーに結び付けられたアセンブリー言語のようなものだ。数学を別のアーキテクチャーで実行したいなら、より一般的なツールを使う必要がある。 8 | 9 | 可能性の1つは、集合の代わりに空間 (space) を使うことだ。空間は構造がより豊かで、集合を使わずに定義できる。空間によく備わっているものの1つは位相 (topology) で、連続性などを定義するために必要だ。位相への従来のアプローチは、ご想像のとおり、集合論によるものだ。特に、部分集合は位相の中心的な概念だ。驚くまでもなく、圏論の研究者たちはこの概念を$\Set$以外の圏に一般化した。集合論に代わるものとしてふさわしい性質を持つ種類の圏は[*トポス*]{.keyword #topos}\index{トポス}(topos, 複数形:トポイtopoi)と呼ばれ、部分集合を一般化した概念などを提供する。 10 | 11 | ## 部分対象分類子 12 | 13 | 要素ではなく関数を使って部分集合の概念を表現することから始めよう。$a$から$b$への任意の関数$f$は、$b$の部分集合――$f$の下での$a$の像――を定義する。しかし、同一の部分集合を定義する関数はたくさんある。もっと絞り込む必要がある。まず初めに、単射関数――複数の要素を1つに潰さない関数に焦点を当てよう。単射関数はある集合を別の集合に「注入」(inject) する。有限集合における単射関数は、ある集合の要素を別の集合の要素に接続するような並行する矢印として視覚化できる。当然、1番目の集合を2番目の集合より大きくはできない。そうでないと矢印は必然的に合流する。まだ曖昧さは残っている。別の集合$a'$と、その集合から$b$への別の単射関数$f'$があって、同じ部分集合が選ばれる可能性がある。しかし、そのような集合が$a$と同型でなければならないことは簡単に確認できる。この事実を利用して、部分集合を、余域の同型によって関係付けられた単射関数の族として定義できる。より正確には、2つの単射関数 14 | $$ 15 | \begin{aligned} 16 | f &\Colon a \to b \\ 17 | f' &\Colon a' \to b 18 | \end{aligned} 19 | $$ 20 | が等価になるのは、同型射 21 | $$h \Colon a \to a'$$ 22 | で 23 | $$f = f' \circ h$$ 24 | となるようなものが存在する場合である。 25 | このような等価な単射たちの族は、$b$の部分集合を定義する。 26 | 27 | `\begin{figure}[H] \centering`{=latex} 28 | ![](images/subsetinjection.jpg){width=40%} 29 | `\end{figure}`{=latex} 30 | 31 | \noindent 32 | この定義は、単射関数をモノ射 (monomorphism) に置き換えることで任意の圏に持ち上げられる。念のために言うと、$a$から$b$へのモノ射$m$は普遍性によって定義される^[訳注:モノ射は、第19章1節で名前だけ出てきたものの、詳しい説明はここが初めてである。]。任意の対象$c$および任意の射のペア 33 | $$ 34 | \begin{aligned} 35 | g &\Colon c \to a \\ 36 | g' &\Colon c \to a 37 | \end{aligned} 38 | $$ 39 | で 40 | $$m \circ g = m \circ g'$$ 41 | を満たすものについては$g = g'$である必要がある。 42 | 43 | `\begin{figure}[H] \centering`{=latex} 44 | ![](images/monomorphism.jpg){width=40%} 45 | `\end{figure}`{=latex} 46 | 47 | \noindent 48 | 集合においてこの定義をより理解しやすくするには、関数$m$がモノ射で*ない*ことが何を意味するかを考えるとよい。その場合は$a$の2つの異なる要素が$b$の1つの要素に写されるだろう。そして、それら2つの要素についてのみ違いがある2つの関数$g$と$g'$を見つけられる。$m$を後合成すると、その違いは見えなくなる。 49 | 50 | `\begin{figure}[H] \centering`{=latex} 51 | ![](images/notmono.jpg){width=40%} 52 | `\end{figure}`{=latex} 53 | 54 | \noindent 55 | 部分集合を定義する別の方法もある。特性関数 (characteristic function) と呼ばれる単一の関数を使う方法だ。これは、集合$b$から二元集合$\Omega$への関数$\chi$だ。二元集合の要素の一方は「真」と呼ばれ、他方は「偽」と呼ばれる。この関数は、$b$の要素のうち部分集合の元である要素に「真」を割り当て、そうでない要素に「偽」を割り当てる。 56 | 57 | $\Omega$の要素を「真」と呼ぶことの意味を明確にする必要が残る。ここで標準的なトリックが使える。すなわち、単元集合から$\Omega$への関数を使う。この関数を$\mathit{true}$と呼ぶことにする。 58 | $$\mathit{true} \Colon 1 \to \Omega$$ 59 | 60 | `\begin{figure}[H] \centering`{=latex} 61 | ![](images/true.jpg){width=40%} 62 | `\end{figure}`{=latex} 63 | 64 | \noindent 65 | これらの定義をうまく組み合わせることで、部分対象 (subobject) が何であるかだけでなく、特別な対象$\Omega$についても要素に触れずに定義できる。ここでのアイデアは、射$\mathit{true}$が「総称」部分対象を表すようにしたい、というものだ。$\Set$では、これは2要素の集合$\Omega$から1要素の部分集合を選ぶ。これは最大限に総称的だ。ここで選ばれたものが真部分集合なのは明らかだ。なぜなら、この部分集合には*ない*要素が$\Omega$にはもう1つあるからだ。 66 | 67 | より一般的な条件では、$\mathit{true}$を終対象から*分類対象* (classifying object) $\Omega$へのモノ射として定義する。*部分対象分類子*は$\mathit{true}$を伴った$\Omega$からなる。ただし、分類対象を定義しなければならない。この対象を特性関数に結びつける普遍性が必要となる。$\Set$では、特性関数$\chi$に沿った$\mathit{true}$の引き戻しが、部分集合$a$とそれを$b$に埋め込む単射関数の両方を定義することになる。その引き戻し図式を以下に示す。 68 | 69 | `\begin{figure}[H] \centering`{=latex} 70 | ![](images/pullback.jpg){width=40%} 71 | `\end{figure}`{=latex} 72 | 73 | \noindent 74 | この図式を分析してみよう。引き戻しの式は次のとおりだ。 75 | $$\mathit{true} \circ \mathit{unit} = \chi \circ f$$ 76 | 関数$\mathit{true} \circ \mathit{unit}$は$a$のすべての要素を「真」に写す。したがって、$f$は$a$のすべての要素を、$b$の要素のうち$\chi$が「真」であるものに写す必要がある。定義より、これらは特性関数$\chi$によって指定される部分集合の要素だ。$f$の像はまさに求めていた部分集合となる。引き戻しの普遍性によって$f$は単射だと保証される。 77 | 78 | この引き戻し図式は$\Set$以外の圏の分類対象を定義するのに使える。そのような圏には終対象が必要で、それによってモノ射$\mathit{true}$を定義できる。また、引き戻しも必要だ――実際の要件は、すべての有限の極限を持つことだ(引き戻しは有限の極限の一例だ)[^finite-limit]。これらの仮定の下で、分類対象$\Omega$を、すべてのモノ射$f$について引き戻し図式を完成させる一意な射$\chi$が存在する、という性質によって定義する。 79 | 80 | [^finite-limit]: 訳注:以下の3つ 81 | 82 | 1. 圏$C$がすべての有限の極限を持つ。 83 | 2. 圏$C$がすべての等化子と二項積を持つ。 84 | 3. 圏$C$がすべての引き戻しと終対象を持つ。 85 | 86 | \noindent 87 | に関して、等化子・二項積・引き戻し・終対象がどれも有限極限の一例なので、$1 \Rightarrow 2$と(本文にある)$1 \Rightarrow 3$が成り立つ。逆の$3 \Rightarrow 1$を示すには$3 \Rightarrow 2$と$2 \Rightarrow 1$をそれぞれ示せばよい。詳細はたとえばアウディ『圏論』原著第2版の第5章4節を参照。 88 | 89 | この性質を分析しよう。引き戻しを構築するとき、3つの対象$\Omega$、$b$、$1$と、2本の射$\mathit{true}$、$\chi$が与えられる。引き戻しの存在は、図式を可換にするような2本の射$f$と$\mathit{unit}$(後者は終対象の定義によって一意に決定される)を伴った最適な対象$a$を見つけられることを意味する。 90 | 91 | ここでは異なる連立方程式を解いていることになる。つまり、$a$*と*$b$の両方を変化させることで$\Omega$と$\mathit{true}$について解いている。与えられた$a$および$b$について、モノ射$f \Colon a \to b$がある場合とない場合がある。だが、もしあるなら、何らかの$\chi$の引き戻しであるようにしたい。さらに、この$\chi$が$f$によって一意に決定されるようにしたい。 92 | 93 | モノ射$f$と特性関数$\chi$の間に1対1の対応関係があるとは言えない。なぜなら、引き戻しは同型を除いて一意なだけだからだ。しかし、部分集合を等価な単射の族として以前定義したのを思い出してほしい。これを一般化するには、$b$の部分対象を、$b$への等価なモノ射の族として定義すればよい。このモノ射の族は、先ほどの図式における等価な引き戻しの族と1対1で対応している。 94 | 95 | したがって、$b$の部分対象の集合$\mathit{Sub}(b)$ をモノ射の族として定義でき、それが$b$から$\Omega$への射の集合と同型だと分かる。 96 | $$\mathit{Sub}(b) \cong \cat{C}(b, \Omega)$$ 97 | 偶然にも、これは2つの関手の自然同型だ。言い換えれば、$\mathit{Sub}(-)$ は表現可能(反変)関手であり、その表現は対象$\Omega$だ。 98 | 99 | ## トポス 100 | 101 | トポスは次のような圏だ。 102 | 103 | 1. デカルト閉である。つまり、積・終対象・(積の右随伴として定義される)冪のすべてを持つ。 104 | 1. すべての有限図式について極限を持つ。 105 | 1. 部分対象分類子$\Omega$がある。 106 | 107 | これらの性質によって、トポスはほとんどの用途で$\Set$の代わりになる。さらに、定義から導かれる追加の性質もある。たとえば、トポスは始対象も含めてすべての有限の余極限を持つ。 108 | 109 | 部分対象分類子を終対象2つの余積(和)として――$\Set$におけるのと同様に――定義してみたくなるが、もっと一般化したい。これが当てはまるトポスはブーリアンと呼ばれる。 110 | 111 | ## トポスと論理 112 | 113 | 集合論では、特性関数は、集合の要素についての性質、つまり、一部の要素に対しては真となり他の要素に対しては偽となるような[*述語*]{.keyword #predicate2}\index{述語} (predicate) を定義するものとして解釈できる。述語$\mathit{isEven}$は自然数の集合から偶数の部分集合を選択する。トポスでは、述語の概念を対象$a$から$\Omega$への射に一般化できる。$\Omega$が真理値対象 (truth object) と呼ばれることがあるのはこのためだ。 114 | 115 | 述語は論理の構成要素だ。トポスには、論理を研究するのに必要なすべての道具が揃っている。積は連言(論理積)に対応し、余積は選言(論理和)に対応し、冪は含意に対応する。排中律(または、等価なものとして、二重否定除去)を除く論理学の標準的な公理すべてがトポスにおいて成り立つ。これが、トポスの論理が構成的 (constructive) あるいは直観主義 (intuitionistic) 論理に対応する理由だ。 116 | 117 | 直観主義論理は計算機科学から予想外に支持され、着実に定着していっている。排中律という古典的な概念は、絶対的な真実があるという信念に基づいている。つまり、すべての記述は真か偽のいずれかであり、古代ローマ人が言ったように、*tertium non datur*(第3の道はない)ということだ。しかし、何かの真偽を知るための方法は、それを証明または反証できるかどうかだけだ。証明とはプロセスであり、計算だ――そして、知ってのとおり、計算には時間とリソースがかかる。場合によっては、停止しないこともある。有限の時間で証明できない命題を真だと主張するのは無意味だ。より繊細な真理値対象が備わっているトポスは、興味深い論理をモデル化するための一般的な枠組みを提供している。 118 | 119 | ## 課題 120 | 121 | 1. 特性関数に沿った$\mathit{true}$の引き戻しである関数$f$は単射でなければならないことを示せ。 122 | -------------------------------------------------------------------------------- /japanese/part1/ch01.md: -------------------------------------------------------------------------------- 1 | \part{} 2 | 3 | # 圏:合成の本質 4 | 5 | 圏は、戸惑ってしまうほど単純な概念だ。圏 (category) は複数の[*対象*]{.keyword #object}\index{対象} (object) とそれらをつなぐ[*射*]{.keyword #arrow}\index{射} (arrow, morphism) で構成される^[訳注:arrowを矢、morphismを射として訳し分けている文献もあるが、本書では『圏論の基礎』にならってどちらも射と訳した。]。そのため、圏は図で簡単に表せる。対象は円または点として、射は矢印として描ける。(変化を付けるために、私は対象を子豚、射をロケット花火として描くことがある。) 6 | しかし、圏の本質は*合成* (composition) にある。あるいは、お好みなら、合成の本質は圏だと言っても構わない。射は合成できるので、対象$A$から対象$B$への射があって、さらに対象$B$から対象$C$への別の射があるなら、それらを合成した$A$から$C$への射が必ずある。 7 | 8 | ![圏では、$A$から$B$への射と$B$から$C$への射があるなら、それらを合成した$A$から$C$へ直接向かう射が必ずある。この図には恒等射(後述)がないため、完全な圏ではない。](images/img_1330.jpg "圏では、$A$から$B$への射と$B$から$C$への射があるなら、それらを合成した$A$から$C$へ直接向かう射が必ずある。この図には恒等射(後述)がないため、完全な圏ではない。"){width=80%} 9 | 10 | ## 関数としての射 11 | 12 | すでに抽象的ナンセンスでいっぱいだろうか^[訳注:抽象的ナンセンス (abstract nonsense) は圏論およびその抽象化能力を指す言葉で、数学者が圏論的議論を割愛するときに「……は抽象的ナンセンスによって示される」などのように自虐を込めて使われる。]? 絶望しないでほしい。具体的な話をしよう。射を関数として考えよう。関数$f$が型$A$の引数を取って$B$を返すとする。また、別の関数$g$が$B$を取って$C$を返すとする。$f$の結果を$g$に渡せばそれらを合成できる。つまり$A$を取って$C$を返す新たな関数を定義したことになる。 13 | 14 | 数学では、このような合成を関数同士の間に小さな丸を書いて$g \circ f$のように表す。合成の順序が右から左であることに注意してほしい。これが紛らわしいと感じる人もいるだろう。読者の中には、Unixのパイプ記法 15 | 16 | ```bash 17 | lsof | grep Chrome 18 | ``` 19 | 20 | \noindent 21 | や、F#の前方合成演算子`>>`を見慣れている人もいるかもしれない。どちらも左から右の向きだ。ところが、数学やHaskellの関数は右から左に合成する^[訳注:もっとも、F#には後方合成演算子`<<`もあり、Haskellで`>>>`を使うこともあるので、必ずしも常に本文中の向きで合成するわけではない。]。$g \circ f$を「$g$を$f$の後に("g after f")」合成する、と読めば理解しやすくなる。 22 | 23 | もっとはっきりさせるために、C言語のコードを少々書こう。型`A`の引数を取って型`B`を返す関数`f` 24 | 25 | ```cpp 26 | B f(A a); 27 | ``` 28 | 29 | \noindent 30 | と、別の関数 31 | 32 | ```cpp 33 | C g(B b); 34 | ``` 35 | 36 | \noindent 37 | の合成は次のとおりだ。 38 | 39 | ```cpp 40 | C g_after_f(A a) 41 | { 42 | return g(f(a)); 43 | } 44 | ``` 45 | 46 | \noindent 47 | ここで再び、右から左への合成`g(f(a))`が、今回はC言語で現れた。 48 | 49 | C++の標準ライブラリーには2つの関数を取って合成関数を返すテンプレートがある、と言えたら良かったのだが、そんなものはない。そこで、気分を変えるためにHaskellを少し試してみよう。ここにAからBへの関数の宣言がある。 50 | 51 | ```haskell 52 | f :: A -> B 53 | ``` 54 | 55 | \noindent 56 | 同様に 57 | 58 | ```haskell 59 | g :: B -> C 60 | ``` 61 | 62 | \noindent 63 | これらの合成は次のとおりだ。 64 | 65 | ```haskell 66 | g . f 67 | ``` 68 | 69 | \noindent 70 | Haskellの簡潔さを知ると、C++で単純明快な関数の概念を表現できないのには少し当惑させられる。実際、HaskellではUnicode文字を使えるので、合成を次のようにも書ける。 71 | 72 | ```haskell 73 | g ∘ f 74 | ``` 75 | 76 | \noindent 77 | Unicodeの二重コロンと矢印さえ使える^[訳注:ここでの合成演算子はRing Operator (U+2218)、二重コロンはProportion (U+2237)、矢印はRightwards Arrow (U+2192) を指す。]。 78 | 79 | ```haskell 80 | f ∷ A → B 81 | ``` 82 | 83 | \noindent 84 | ここで、第1回目のHaskellのレッスンだ。二重コロンは「……という型を持つ」を意味する。関数型 (function type) は2つの型の間に矢印を挿入することで作成される。2つの関数を合成するには、間にピリオド(あるいはUnicodeの丸)を置く。 85 | 86 | ## 合成の性質 87 | 88 | どんな圏においても合成が満たすべき非常に重要な性質が2つある。 89 | 90 | 1. 合成は結合的 (associative) である。3本の射$f$, $g$, $h$があり、それらが合成できる(つまり端同士の対象が一致している)なら、合成するときに括弧は要らない。このことは数学の記法では次のように表される。 91 | $$h \circ (g \circ f) = (h \circ g) \circ f = h \circ g \circ f$$ 92 | (擬似的な)Haskellでは次のように書ける。 93 | 94 | ```haskell 95 | f :: A -> B 96 | g :: B -> C 97 | h :: C -> D 98 | h . (g . f) == (h . g) . f == h . g . f 99 | ``` 100 | 101 | \noindent 102 | (ここで「擬似的」と呼んだのは、関数に等しさが定義されていないからだ。) 103 | 104 | 関数を扱うなら結合性は全く自明だが、その他の圏では自明ではないこともある。 105 | 106 | 1. どんな対象$A$にも、合成の単位元 (unit) となる射が1本ずつ存在する。その射は対象から対象自身へとループを描く。合成の単位元となるというのは、$A$から始まるか$A$で終わるどんな射と合成しても、もとと同じ射になるという意味だ。対象Aについて単位元となる射は$\idarrow[A]$($A$上の[*恒等射*]{.keyword #identity}\index{恒等射}、identity)と呼ばれる。数学の表記法では、$f$が$A$から$B$へ向かうなら 107 | $$f \circ \idarrow[A] = f$$ 108 | かつ 109 | $$\idarrow[B] \circ f = f$$ 110 | となる。 111 | 112 | \noindent 113 | 関数を扱うとき、恒等射は引数をそのまま返す恒等関数として実装される。この実装はどの型でも同じであり、この関数は普遍的に多相 (universally polymorphic) であることを意味する。これはC++ではテンプレートとして定義できる。 114 | 115 | ```cpp 116 | template T id(T x) { return x; } 117 | ``` 118 | 119 | \noindent 120 | もちろん、C++ではそれほど単純ではない。何を渡すかだけでなく、どのように渡すか(値渡し・参照渡し・const参照渡し・ムーブなど)も考慮する必要があるからだ。 121 | 122 | Haskellの恒等関数は、(Preludeと呼ばれる)標準ライブラリーの一部だ。宣言と定義は以下のとおりだ。 123 | 124 | ```haskell 125 | id :: a -> a 126 | id x = x 127 | ``` 128 | 129 | \noindent 130 | ご覧のとおり、Haskellの多相関数は朝飯前だ。宣言において、型を型変数に置き換えるだけでよい。トリックは次のとおりだ。具体的な型の名前は常に大文字で始まり、型変数の名前は小文字で始まる。ここで`a`はすべての型を表している。 131 | 132 | Haskellの関数定義は、関数の名前とそれに続く仮引数 (formal parameter) ――ここでは`x`ただひとつ――で構成される。関数の本体は等号の後に続く。この簡潔さは、多くの初心者には衝撃的だが、すぐに完全に理にかなっていることが分かるだろう。関数定義と関数呼び出しは関数プログラミングの必需品なので、構文は最小限に抑えられている。引数リストを括弧で囲まないだけでなく、引数間のコンマさえない(これについては後ほど複数の引数の関数を定義するときに説明する)。 133 | 134 | 関数の本体は常に式 (expression) であり、関数内に文 (statement) はない。関数の結果はその式だ――ここでは単に`x`だ。 135 | 136 | これでHaskellのレッスンの第2回は終了だ。 137 | 138 | 恒等条件は、(再び疑似Haskellで)次のように書ける。 139 | 140 | ```haskell 141 | f . id == f 142 | id . f == f 143 | ``` 144 | 145 | \noindent 146 | 誰が恒等関数――何もしない関数――をわざわざ気にするのか、と疑問に思うかもしれない。では、なぜ0という数をわざわざ気にするのだろうか? 0は無の象徴だ。古代ローマ人は0のない数値体系を使っていたが、優れた道路や水路を建設でき、その一部は今日まで残っている。 147 | 148 | 0や$\id$のような中立の値は、記号変数を扱うときに非常に便利だ。これこそが、ローマ人は代数があまり得意ではなく、0の概念に精通していたアラビア人やペルシア人は得意だった理由だ。そのため、恒等関数は、高階関数 (higher-order function) の引数あるいは戻り値として非常に便利になる。高階関数は関数の記号的操作を可能にする。それらは関数の代数だ。 149 | 150 | 要約すると、圏は対象と射で構成されている。射は合成でき、その合成は結合性を持つ。すべての対象には、合成の単位元として機能する恒等射がある。 151 | 152 | ## 合成はプログラミングの本質 153 | 154 | 関数プログラマーは、問題に独特の方法でアプローチする。彼らはまるで禅のような問いから始める。たとえば、対話型プログラムを設計するときは「対話とは何か?」と問うだろう。コンウェイのライフゲームを実行するときには、生命の意味について思索するだろう。そのような精神で「プログラミングとは何か?」と問いかけたい。最も基本的なレベルでは、プログラミングとはコンピューターに何をすべきかを指示することだ。「メモリーアドレス`x`の内容を取り、レジスタ`EAX`の内容に加えよ」のように。しかし、アセンブリー言語でプログラムを作成する場合でも、コンピューターに与える命令はもっと意味のあるものを表現している。解こうとしているのは自明な問題ではないのだ(自明ならコンピューターの助けは不要だろう)。どうすれば問題を解けるだろうか? 大きな問題を小さな問題に分解すればよい。小さくした問題がまだ大きすぎる場合は、それらをさらに分解する。最後に、小さな問題すべてについて、解決するコードを書く。そうしてプログラミングの本質が現れる。すなわち、それらのコードを合成し、より大きな問題に対する解決策を創造する。分解は、断片をもとの状態に戻せなければ意味がない。 155 | 156 | この階層的な分解と再合成のプロセスは、コンピューターによって強制されているわけではない。それは人間の精神の限界を反映しているのだ。脳は一度に少しの概念しか扱えない。心理学で最も引用された論文の1つ、[*The Magical Number Seven, Plus or Minus Two*](https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two)[^magical]は、我々は$7 \pm 2$の「チャンク」の情報しか保持できないと仮定した。人間の短期記憶に関する我々の理解の詳細は変化しているかもしれないが、限界があるのは確実に分かっている。要するに、我々はオブジェクトのスープやコードのスパゲッティを扱えないということだ。構造が必要なのは、よく構造化されたプログラムが見やすいからではなく、そうでなければ脳が効率的に処理できないからだ。あるコード断片について、エレガントだ、あるいは美しいと形容することがよくある。だが、本当に意味しているのは、人間の限界ある精神で処理するのが簡単だということだ。エレガントなコードは、ちょうど適切なサイズのチャンクを作成し、精神の消化器系がそれらを消化するのにちょうど適切な数だけ生成する。 157 | 158 | [^magical]: 159 | 160 | 訳注:論文はを参照。 161 | 162 | では、プログラムの合成にとって適切なチャンクとは何だろうか。チャンクの表面積は体積よりも必ずゆっくりと増加する。(私がこのたとえを気に入っているのは、幾何学的な対象の表面積はその大きさの2乗に比例して増加する――体積が大きさの3乗に比例して増加するのよりも遅い――という直観による。)表面積は、チャンクを合成するために必要な情報だ。体積は、それらを実装するために必要な情報だ。そのこころは、ひとたびチャンクが実装されると、その実装の詳細を忘れて他のチャンクとの相互作用に集中できる、ということだ。オブジェクト指向プログラミングでは、表面はオブジェクトのクラス宣言、あるいはその抽象インターフェイスだ。関数プログラミングでは、それは関数の宣言だ^[訳注:ここでは型シグネチャーのこと。]。(ここでは少し単純化しているが、要点はこれだ。) 163 | 164 | 圏論は、対象の中を見ることを積極的に思いとどまらせるという意味で極端だ。圏論における対象は抽象的で漠然とした存在だ。対象について知り得るのは、他の対象たちとどのように関連しているか、つまり、どのように射で接続しているかだけだ。これは、インターネット検索エンジンが流入リンクと流出リンクを分析してウェブサイトを順位付けするやり方だ(不正行為がある場合は除く)。オブジェクト指向プログラミングでは、理想化されたオブジェクトを見られるのは抽象インターフェイス(純粋な表面なので体積なし)を通してだけで、メソッドが射の役割を果たす。他のオブジェクトと合成する方法を理解するためにオブジェクトの実装を掘り下げなければならなくなった瞬間、このプログラミングパラダイムの利点は失われてしまう。 165 | 166 | ## 課題 167 | 168 | 1. 恒等関数を、好きな言語で(それがたまたまHaskellなら2番目に好きな言語で)できるだけうまく実装せよ。 169 | 170 | 1. 合成関数を好きな言語で実装せよ。このメソッドは2つの関数を引数として受け取り、その合成である関数を返す。 171 | 172 | 1. 合成関数が恒等関数と整合しているかテストするプログラムを作成せよ。 173 | 174 | 1. ワールドワイドウェブは、何らかの意味で圏だろうか? リンクは射だろうか? 175 | 176 | 1. Facebookは人を対象とし友達関係を射とする圏だろうか? 177 | 178 | 1. 有向グラフが圏になるのはどのような場合だろうか? 179 | -------------------------------------------------------------------------------- /japanese/part2/ch03.md: -------------------------------------------------------------------------------- 1 | # 自由モノイド {#free-monoids} 2 | 3 | モノイドは圏論とプログラミングの両方において重要な概念となる。圏は強く型付けされた言語に対応し、モノイドは型なし言語に対応する。型なしの言語で任意の2つの関数を合成できる(当然、プログラムを実行したときにランタイムエラーが発生する可能性はある)ように、モノイドでは任意の2本の射を合成できるからだ。 4 | 5 | これまでに見てきたように、モノイドは単一の対象を持つ圏として記述され、その圏ではすべての論理が射の合成の規則として表現されている。この圏論的モデルは、より伝統的で集合論的なモノイドの定義と完全に等価だ。そこでは集合の2つの要素を「乗算」することで第3の要素が得られる。この「乗算」の過程はさらに細かく分割できる。すなわち、まず要素のペア1つを形成するという過程と、次にこのペアを既存の要素――それらの「積」と同一視するという過程だ。 6 | 7 | 乗算の2番目の部分、つまりペアと既存の要素との同一視を省くとどうなるだろうか? たとえば、任意の集合から始めて、ペアにできる要素をすべてペアにし、それらを新しい要素と呼ぶことができる。次に、それらの新しい要素とペアにできる要素をすべてペアにしていく。以下同様だ。これは連鎖反応だ――新しい要素を永久に追加し続けられる。その結果は、無限集合であり、*ほぼ*モノイドとなる。ただし、モノイドには単位元と結合律も必要となる。しかし、問題ない。特別な単位元を追加し、生成されたペアの一部を同一視すれば、単位律 (unit law) と結合律をきちんと満たせる。 8 | 9 | 実際にどうなるかを簡単な例で見てみよう。2要素の集合$\{a, b\}$から始めることにしよう。それらの要素を自由モノイドの生成元 (generator) と呼ぶことにする。まず、単位元となる特別な要素$e$を追加する。次に、要素のすべてのペアを追加し、それらを「積」と呼ぶ。$a$と$b$の積はペア $(a, b)$ となる。$b$と$a$の積はペア $(b, a)$ となり、$a$と$a$の積は $(a, a)$ となり、$b$と$b$の積は $(b, b)$ となる。$e$とのペアも作れて、$(a, e)$ や $(e, b)$ などになるが、それらは$a$や$b$などと同一視することにする。結局このラウンドでは $(a, a)$、$(a, b)$、$(b, a)$、$(b, a)$、$(b, a)$、$(b, b)$ だけを追加して、結果として$\{e, a, b, (a, a), (a, b), (b, a), (b, b)\}$という集合が得られる。 10 | 11 | `\begin{figure}[H] \centering`{=latex} 12 | ![](images/bunnies.jpg){width="80%"} 13 | `\end{figure}`{=latex} 14 | 15 | \noindent 16 | 次のラウンドでは $(a, (a, b))$ や $((a, b), a)$ といった要素を追加していく。この時点で、結合律が確実に満たされるようにする必要がある。そのため、たとえば$(a, (b, a))$ と $((a, b), a)$ を同一視する。要するに、内側の括弧は必要ないということだ。 17 | 18 | このプロセスの最終的な結果が予想できるだろう。要素が$a$か$b$であるようなすべてのリストが作られる。実際、$e$を空リストで表せば、「乗算」はリストの連接に他ならないことが分かる。 19 | 20 | この種の構成では、要素の組み合わせとして可能なものすべてを生成し続け、同一視は最小限に――その構造の規則を維持するのにちょうど十分なだけに留める。こういった構成は自由構成と呼ばれる。上記では、生成元の集合$\{a, b\}$から[*自由モノイド*]{.keyword #free_monoid}\index{自由モノイド}を構築した。 21 | 22 | ## Haskellにおける自由モノイド 23 | 24 | Haskellにおける二元集合は型`Bool`と等価であり、この集合から生成される自由モノイドは型`[Bool]`(`Bool`のリスト)と等価だ。(無限リストの問題は意図的に無視している。) 25 | 26 | Haskellのモノイドは型クラスによって定義されている。 27 | 28 | ```haskell 29 | class Monoid m where 30 | mempty :: m 31 | mappend :: m -> m -> m 32 | ``` 33 | 34 | \noindent 35 | このクラスが意味しているのは、すべての`Monoid`が`mempty`と呼ばれる中立元と、`mappend`と呼ばれる二項関数(乗算)を持たなければならないということだ。Haskellでは単位律と結合律は表現できず、具体的なモノイドを与えるたびにプログラマーによって検証されなければならない。 36 | 37 | 任意の型のリストがモノイドをなすという事実は、次のインスタンス定義によって説明される。 38 | 39 | ```haskell 40 | instance Monoid [a] where 41 | mempty = [] 42 | mappend = (++) 43 | ``` 44 | 45 | \noindent 46 | これはリストモノイドについて、空リスト`[]`が単位元であり、リスト連接`(++)`が二項演算であることを述べている。 47 | 48 | これまで見てきたように、型`a`のリストは集合`a`を生成元たちとする自由モノイドに対応する。その一方で、乗算を伴う自然数の集合は、多くの積が同一視されるので自由モノイドではない。次の2つを比べてみよう。 49 | 50 | ```haskell 51 | 2 * 3 = 6 52 | [2] ++ [3] = [2, 3] -- [6]と同じではない 53 | ``` 54 | 55 | \noindent 56 | これは簡単な例だったが、圏論では対象の中を見るのが許されないのにどうやってこの自由構成を実現できるのか、という疑問がある。そこで我々の働き者にもうひと仕事してもらうとしよう。普遍的構成だ。 57 | 58 | 2番目の興味深い疑問は、単位律と結合律が最小限必要とするよりも多くの要素を同一視すれば、ある自由モノイドから任意のモノイドを得られるのか、ということだ。これが普遍的構成から直接導かれることをお見せしよう。 59 | 60 | ## 自由モノイドの普遍的構成 61 | 62 | 普遍的構成についての経験を振り返れば、それは何かを構築するというより、特定のパターンに最もよく適合する対象を選択するものだと気付くだろう。なので、普遍的構成を使って自由モノイドを「構築」したいなら、選択肢となる多数のモノイドの全体を考慮する必要がある。つまり、選択のもととなるモノイドの圏がまるごと必要だ。だが、モノイドたちは圏をなすのだろうか^[訳注:この章の冒頭ではモノイドと単一対象の圏との対応について述べていたが、ここではモノイドが対象であるような圏について述べていることに注意。]? 63 | 64 | まずは、単位元と二項演算による構造が加わった集合としてモノイドを見てみよう。そして、モノイドの構造を保存するような関数を射として採用する。構造を保存するそういった関数は[*準同型*]{.keyword #homomorphisms}\index{準同型} (homomorphism) と呼ばれる。モノイド準同型は2つの要素の積を2つの要素の写し先の積へと写さなければならない。 65 | 66 | ```haskell 67 | h (a * b) = h a * h b 68 | ``` 69 | 70 | \noindent 71 | そして、単位元を単位元に写さなければならない。 72 | 73 | 例として、整数のリストから整数への準同型を考えよう^[訳注:ここでは二項演算が乗算であるようなモノイド構造を考えている。]。`[2]`を2に写し、`[3]`を3に写すなら、`[2, 3]`を6に写す必要がある。なぜなら、連接 74 | 75 | ```haskell 76 | [2] ++ [3] = [2, 3] 77 | ``` 78 | 79 | \noindent 80 | が次のような乗算に写されるからだ。 81 | 82 | ```haskell 83 | 2 * 3 = 6 84 | ``` 85 | 86 | \noindent 87 | ここで、個々のモノイドの内部構造については忘れて、対応する射を持つ対象としてのみ見よう。すると、モノイドの圏$\cat{Mon}$が得られる。 88 | 89 | さて、内部構造を忘れる前に、重要な性質に注目しておいた方がよいだろう。$\cat{Mon}$のどの対象も自明に集合へと写せる。写し先の集合は単にもとのモノイドの要素の集合である。この集合は[*台*]{.keyword #underlying}\index{台}集合 (underlying set) と呼ばれる。実際には、$\cat{Mon}$の各対象を集合に写せるだけでなく、$\cat{Mon}$の各射(準同型)も関数に写せる。これも自明なだけに見えるが、すぐに役に立つ。この$\cat{Mon}$から$\Set$への対象と射の写像は、実は関手になっている。この関手はモノイドの構造を「忘れている」。いったん通常の集合の中に入ると、もはや単位元を区別したり乗算を気にしたりすることはない。こういった関手は[*忘却関手*]{.keyword #forgetful_functor}\index{忘却関手} (forgetful functor) と呼ばれる。忘却関手は圏論ではよく出てくる。 90 | 91 | これで、2つの異なる観点から$\cat{Mon}$を見たことになる。$\cat{Mon}$は対象と射を伴う他のすべての圏と同じように扱える。この観点では、モノイドの内部構造は見えない。$\cat{Mon}$の中の特定の対象について言えるのは、それ自身や他の対象と射を通じて接続しているということだけだ。射の「乗算」表――つまり、合成の規則――は、もう一方の観点から導かれる。すなわち、集合としてのモノイドからである。圏論に進んだことでこの観点が完全に失われたわけではない――忘却関手を通じてならアクセスできる。 92 | 93 | 普遍的構成を適用するには、モノイドの圏を探索して自由モノイドの最も優れた候補を選べるようにするための特別な性質を定義する必要がある。しかし、自由モノイドはその生成元たちによって定義される。別の生成元たちを選べば、生成される自由モノイドは変わる(`Bool`のリストと`Int`のリストは違う)。我々の構成は、生成元の集合から始めなければならない。つまり、集合に戻ってきたということだ! 94 | 95 | ここで忘却関手が役立つことになる。忘却関手によってモノイドをレントゲン撮影できる。そして、それらのかたまりたちのレントゲン写真から生成元たちを特定できる。その仕組みは以下のとおりだ。 96 | 97 | 生成元の集合$x$から始める。この集合は$\Set$の対象だ。 98 | 99 | マッチさせようとしているパターンは、モノイド$m$――$\cat{Mon}$の対象――と$\Set$内の関数$p$で構成されている。 100 | 101 | ```haskell 102 | p :: x -> U m 103 | ``` 104 | 105 | \noindent 106 | ここで、$U$は$\cat{Mon}$から$\Set$への忘却関手だ。これは奇妙な混成パターンだ――半分は$\cat{Mon}$で半分は$\Set$になっている。 107 | 108 | 意図としては、$m$のレントゲン写真に写った生成元の集合が関数$p$によって特定されるようにするということだ。関数たちが集合内の点たち^[訳注:$m$の生成元たちのこと。]をきちんと特定できない(それらを潰す)かもしれないことは問題ない。普遍的構成によってこのパターンの最も優れた代表が選ばれ、すべてが整理されるだろう[^sub-monoid]。 109 | 110 | [^sub-monoid]: 訳注:一般の$m$について、ある$p$による$x$の像は$m$の全体を生成するとは限らず、ある部分モノイドを生成する。$m$が自由モノイド(後述の順位付けにおける最も優れた候補)ならば全体が生成される。 111 | 112 | `\begin{figure}[H] \centering`{=latex} 113 | ![](images/monoid-pattern.jpg){width="40%"} 114 | `\end{figure}`{=latex} 115 | 116 | \noindent 117 | 候補間の順位付けも定義しなければならない。もう1つの候補があるとしよう。モノイド$n$と、そのレントゲン写真に写った生成元たちを特定しようとする関数だ。 118 | 119 | ```haskell 120 | q :: x -> U n 121 | ``` 122 | 123 | \noindent 124 | 以下のような条件を満たす場合、$m$は$n$よりも優れていると言うことにしよう。その条件とは、モノイドの射(準同型なので構造を保存する) 125 | 126 | ```haskell 127 | h :: m -> n 128 | ``` 129 | 130 | \noindent 131 | があり、その$U$の下の像($U$は関手なので射を関数に写す)が$p$を通じて$q$を分解することだ。 132 | 133 | ```haskell 134 | q = U h . p 135 | ``` 136 | 137 | \noindent 138 | $p$が$m$内で生成元たちを選択し、$q$が$n$内で「同じ」生成元たちを選択していると見なすなら、$h$はこれらの生成元たちを2つのモノイドの間で写していると見なせる。$h$は、定義より、モノイドの構造を保存することを思い出してほしい。これは、一方のモノイドにおける2つの生成元の積が、もう一方のモノイドにおける対応する2つの生成元の積に写されることなどを意味する。 139 | 140 | `\begin{figure}[H] \centering`{=latex} 141 | ![モノイドの順位付け](images/monoid-ranking.jpg){width="40%"} 142 | `\end{figure}`{=latex} 143 | 144 | \noindent 145 | この順位付けは、最も優れた候補、すなわち自由モノイドを見つけるために使われる。定義は次のとおりだ。 146 | 147 | >(関数$p$を伴う)$m$を生成元$x$を伴う**自由モノイド**と呼ぶのは、$m$から(関数$q$を伴う)他の任意のモノイド$n$への、前述の分解特性を満たす*一意な*射$h$が存在する場合、かつその場合に限る。 148 | 149 | ところで、これは2番目の疑問に対する答えになっている。関数$U h$には、$U m$の複数の要素を$U n$の1つの要素へ潰す力がある。ここで、潰すことは自由モノイドのいくつかの要素を同一視することに対応する。したがって、生成元たちとして$x$を持つモノイドはどれも、$x$に基づく自由モノイドから、いくつかの要素を同一視することによって得られる。自由モノイドとは、最小限のものだけしか同一視されていないモノイドのことだ。 150 | 151 | 自由モノイドについては、随伴について話すときにまた戻ってくることにしよう。 152 | 153 | ## 課題 154 | 155 | 1. モノイドの準同型が単位元を保存する、という条件は(当初は私もそう思ったように)冗長だと思うかもしれない。何しろ、すべての$a$について次が言えるのだから。 156 | 157 | ```haskell 158 | h a * h e = h (a * e) = h a 159 | ``` 160 | 161 | \noindent 162 | つまり、$h e$は右単位元のように働く(同様に、左単位元のようにも働く)。問題は、すべての$a$に対して$h a$を集めてきたものを考えると、余域モノイドの部分モノイドしかカバーできないということだ。$h$の像の外部に「真の」単位元が存在するかもしれない。モノイド間で乗算を保存する同型は自動的に単位元を保存することになることを示せ。 163 | 164 | 1. 連接を二項演算とする整数リストから乗算を二項演算とする整数へのモノイド準同型について考える。空リスト`[]`の像は何か? すべての単要素リストは、それが含む整数に写されるとする。たとえば、`[3]`は3に写される。`[1, 2, 3, 4]`の像は何か? 整数12に写されるリストはいくつあるか? 2つのモノイド間に他の準同型はあるか? 165 | 166 | 1. 単元集合によって生成される自由モノイドとは何か? それが何と同型なのか分かるか? 167 | -------------------------------------------------------------------------------- /japanese/part3/ch15.md: -------------------------------------------------------------------------------- 1 | # モナド・モノイド・圏 2 | 3 | 圏論の本を終えるのにふさわしいところというものはない。学ぶべきことは常にもっとある。圏論は広大な題材だ。一方で、同じテーマ・コンセプト・パターンが明らかに何度も繰り返されている。すべての概念はカン拡張である^[訳注:『圏論の基礎』第X章7節のこと。]という格言があるとおり、確かにカン拡張を使えば極限・余極限・モナド・米田の補題などを導出できる。圏の概念自体は抽象化のあらゆるレベルに現れる。モノイドとモナドの概念も同様だ。最も基本となるものはどれだろうか? 結局のところ、それらはすべて相互に関連しており、抽象化の終わりのないサイクルのなかで一方からもう一方が導かれる。それらの相互関係を示すことが、この本を締めくくるのにふさわしいだろうと判断した。 4 | 5 | ## 双圏 6 | 7 | 圏論で特に難しい側面の1つは、絶えず視点が切り替わることだ。たとえば、集合の圏を考えてみてほしい。我々は要素によって集合を定義することに慣れている。空集合には要素がない。単元集合には要素が1つある。2つの集合のデカルト積はペアの集合である、などなど。しかし、$\Set$圏について述べるとき、集合の内容を忘れて、代わりにそれらの間の射(矢)に集中するように求めた。だが時折、$\Set$内の特定の普遍的構成が要素の言葉でどう表現されるのかを知るため、カバーの下を覗くことが許された。そうして、終対象は実は単元集合であることなどが分かった。しかし、それらはサニティーチェックにすぎなかった。 8 | 9 | 関手は圏の写像として定義される。写像を圏内の射と見なすのは自然である。関手は、圏(サイズに関する問題を避けたいなら、小さい圏)の圏における射だった。関手を射として扱うと、圏の内部(対象と射)に対するその作用についての情報を代わりに失うことになる。これは、関数が集合の要素に対してどう作用するかの情報が、その関数を$\Set$内の射として扱うと代わりに失われるのと同じだ。その一方、任意の2つの圏の間の関手たちも圏をなす。今度は、ある圏の射であったものを別の圏の対象と見なすことが求められる。関手圏では関手が対象であり、自然変換が射だ。同一のものが、ある圏では射であり、別の圏では対象であり得ることが発見された。対象を名詞とし射を動詞とする素朴な考え方は成り立たない。 10 | 11 | 2つの観点を切り替える代わりに、1つの観点への統合を試みることもできる。そうすることで$\cat{2}$-圏の概念が得られる。この圏では、対象を$0$-セル、射を$1$-セル、射間の射を$2$-セルと呼ぶ。 12 | 13 | ![$0$-セル$a, b$、$1$-セル$f, g$、および$2$-セル$\alpha$。](images/twocat.png "$0$-セル$a, b$、$1$-セル$f, g$、および$2$-セル$\alpha$。"){width=35%} 14 | 15 | \noindent 16 | 目下の例は圏の圏$\Cat$だ。圏が$0$-セル、関手が$1$-セル、自然変換が$2$-セルとなる。$\cat{2}$-圏の規則が示すのは、任意の2つの$0$-セル間の$1$-セルが圏をなす(言い換えると、[訳注:いま話している$2$-圏を$\cat{C}$と書くと]$\cat{C}(a, b)$ はhom集合ではなくhom圏である)ことだ。このことは、任意の2つの圏の間の関手は関手圏をなすという以前の主張とよく一致している。 17 | 18 | 特に、任意の$0$-セルからそれ自体に戻る$1$-セルもhom圏$\cat{C}(a, a)$ をなす。だが、その圏はさらなる構造を持っている。$\cat{C}(a, a)$ のメンバーは、$\cat{C}$内の射とも$\cat{C}(a, a)$ 内の対象とも見なせる。これらは射なので互いに合成できる。しかし、それらを対象として見ると、合成は対象のペアから対象への写像になる。実際、それは積に――正確にはテンソル積に――非常によく似ている。このテンソル積は恒等$1$-セルという単位元を持つ。任意の$\cat{2}$-圏において、hom圏$\cat{C}(a, a)$ は自動的に、テンソル積が$1$-セルの合成として定義されるようなモノイダル圏になる。結合律と単位律は、対応する圏の規則から単に成り立つ。 19 | 20 | これが何を意味するのかを、$\cat{2}$-圏のカノニカルな例である$\Cat$で見てみよう。hom圏$\Cat(a, a)$ は$a$上の自己関手の圏だ。その中では、自己関手の合成がテンソル積の役割を果たす。恒等関手はこの積の単位元だ。自己関手がモノイダル圏をなすことは以前にも見た(その事実をモナドの定義で使った)が、これはもっと一般的な現象なのだ。つまり、任意の$\cat{2}$-圏において自己-$1$-セルはモノイダル圏をなす。これについては、後でモナドを一般化するときに再度説明する。 21 | 22 | 覚えているかもしれないが、一般のモノイダル圏では、モノイド則がきっちりと満たされていることは主張しなかった。多くの場合、単位律と結合律が同型を除いて満たされていれば十分だった。$\cat{2}$-圏では、$\cat{C}(a, a)$ のモノイド則は$1$-セルの合成律から導かれる。これらの規則は厳密なので、厳密モノイダル圏が常に得られる。しかし、これらの規則も緩和できる。たとえば、恒等$1$-セル$\idarrow[a]$と別の$1$-セル$f \Colon a \to b$の合成は、$f$と等しいのではなく、同型なのだと主張できる。$1$-セルの同型は$2$-セルを用いて定義される。つまり、次のような$2$-セル 23 | $$\rho \Colon f \circ \idarrow[a] \to f$$ 24 | と、その逆が存在する。 25 | 26 | ![双圏の恒等律は同型(可逆な$2$-セル$\rho$)を除いて成り立つ。](images/bicat.png "双圏の恒等律は同型(可逆な$2$-セル$\rho$)を除いて成り立つ。"){width=35%} 27 | 28 | \noindent 29 | 左恒等射と結合律についても同じことができる。このような緩和された$\cat{2}$-圏は双圏と呼ばれる(いくつか追加のコヒーレンス則があるが、ここでは省略する)。 30 | 31 | 予想どおり、双圏での自己-$1$-セルは、規則が厳密でない一般化されたモノイダル圏をなす。 32 | 33 | 双圏の興味深い例としてスパンの圏が挙げられる。2つの対象$a$と$b$の間のスパンは、対象$x$および次の1対の射だ。 34 | $$ 35 | \begin{gathered} 36 | f \Colon x \to a \\ 37 | g \Colon x \to b 38 | \end{gathered} 39 | $$ 40 | 41 | `\begin{figure}[H] \centering`{=latex} 42 | ![](images/span.png){width=35%} 43 | `\end{figure}`{=latex} 44 | 45 | \noindent 46 | 圏論的な積の定義でスパンを使ったことを覚えているかもしれない。ここでは、スパンを双圏での$1$-セルと見なしたい。最初のステップは、スパンの合成を定義することだ。隣接したスパンがあるとする。 47 | $$ 48 | \begin{gathered} 49 | f' \Colon y \to b \\ 50 | g' \Colon y \to c 51 | \end{gathered} 52 | $$ 53 | 54 | `\begin{figure}[H] \centering`{=latex} 55 | ![](images/compspan.png){width=50%} 56 | `\end{figure}`{=latex} 57 | 58 | \noindent 59 | それらの合成はある$z$を頂点とするような第3のスパンになるだろう。最も自然な選択は、$f'$に沿った$g$の引き戻しだ。引き戻しとは対象$z$に2本の射 60 | $$ 61 | \begin{gathered} 62 | h \Colon z \to x \\ 63 | h' \Colon z \to y 64 | \end{gathered} 65 | $$ 66 | ただし、 67 | $$g \circ h = f' \circ h'$$ 68 | を伴ったもので、そのような対象すべての中で普遍なものであることを思い出してほしい。 69 | 70 | `\begin{figure}[H] \centering`{=latex} 71 | ![](images/pullspan.png){width=35%} 72 | `\end{figure}`{=latex} 73 | 74 | \noindent 75 | ここでは、集合の圏でのスパンに注目しよう。この場合、引き戻しはデカルト積$x \times y$からのペア $(p, q)$ のうち次を満たすものの集合となる。 76 | $$g\ p = f'\ q$$ 77 | 同じ端点を共有する2つのスパンの間の射は頂点間の射$h$として定義され、適切な三角形を可換にする。 78 | 79 | ![$\cat{Span}$内の$2$-セル。](images/morphspan.png "$\cat{Span}$内の$2$-セル。"){width=35%} 80 | 81 | \noindent 82 | まとめると、双圏$\cat{Span}$では、$0$-セルは集合、$1$-セルはスパン、$2$-セルはスパン間の射だ。恒等$1$-セルは、3つの対象すべてが同じで、2本の射が恒等射であるような退化 (degenerate) したスパンだ。 83 | 84 | 双圏の別の例もすでに見ている。それは[プロ関手](#ends-and-coends)の双圏$\cat{Prof}$であり、$0$-セルは圏、$1$-セルはプロ関手、$2$-セルは自然変換だ。プロ関手の合成はコエンドによって与えられる。 85 | 86 | ## モナド 87 | 88 | ここまでで、自己関手の圏におけるモノイドとしてのモナドの定義にかなり精通しているはずだ。この定義を、自己関手の圏は双圏$\Cat$内の自己-$1$-セルの取るに足らないhom圏のひとつにすぎないという新たな理解に沿って再検討してみよう。自己関手の圏がモノイダル圏であることは知っている。そのテンソル積は自己関手の合成に由来する。モノイドは、モノイダル圏内の対象――ここでは自己関手$T$――が2本の射を伴ったものとして定義される。自己関手間の射は自然変換だ。一方の射はモノイドの単位元――恒等自己関手――を$T$に写す。 89 | $$\eta \Colon I \to T$$ 90 | もう一方の射はテンソル積$T \otimes T$を$T$に写す。このテンソル積は自己関手の合成によって与えられるため、次が得られる。 91 | $$\mu \Colon T \circ T \to T$$ 92 | 93 | `\begin{figure}[H] \centering`{=latex} 94 | ![](images/monad.png){width=30%} 95 | `\end{figure}`{=latex} 96 | 97 | \noindent 98 | これらがモナドを定義する2つの操作である(Haskellでは`return`および`join`と呼ばれる)ことが確認でき、そしてモノイド則がモナド則になったことが分かる。 99 | 100 | さて、この定義から自己関手に関する記述をすべて取り除いていこう。まず双圏$\cat{C}$から始めて、その中で$0$-セル$a$を選ぶ。すでに見たように、hom圏$\cat{C}(a, a)$ はモノイダル圏だ。したがって、$\cat{C}(a, a)$ のモノイドを、$1$-セル$T$、および2つの$2$-セル 101 | $$ 102 | \begin{gathered} 103 | \eta \Colon I \to T \\ 104 | \mu \Colon T \circ T \to T 105 | \end{gathered} 106 | $$ 107 | でモノイド則を満たすものとして定義できる。*これのことを*モナドと呼ぶ。 108 | 109 | `\begin{figure}[H] \centering`{=latex} 110 | ![](images/bimonad.png){width=30%} 111 | `\end{figure}`{=latex} 112 | 113 | \noindent 114 | これは、$0$-セルと$1$-セルと$2$-セルだけを用いた、はるかに一般的なモナドの定義になっている。双圏$\Cat$に適用すると、これは単に通常のモナドになる。だが、他の双圏では何が起こるか見てみよう。 115 | 116 | $\cat{Span}$でモナドを構築してみよう。ここでは$0$-セルを選択する。これは集合であり、すぐ明らかになる理由から、$\mathit{Ob}$と呼ぶことにする。次に、自己-$1$-セル($\mathit{Ob}$から$\mathit{Ob}$へ戻るスパン)を選択する。その頂点には$\mathit{Arr}$と呼ぶことにする集合があり、次の2つの関数を伴う。 117 | $$ 118 | \begin{gathered} 119 | \mathit{dom} \Colon \mathit{Arr} \to \mathit{Ob} \\ 120 | \mathit{cod} \Colon \mathit{Arr} \to \mathit{Ob} 121 | \end{gathered} 122 | $$ 123 | 124 | `\begin{figure}[H] \centering`{=latex} 125 | ![](images/spanmonad.png){width=30%} 126 | `\end{figure}`{=latex} 127 | 128 | \noindent 129 | 集合$\mathit{Arr}$の要素を「射」と呼ぶことにしよう。さらに、$\mathit{Ob}$の要素を「対象」と呼ぶことにする、と言えば、目的地の手掛かりになるだろうか。2つの関数$\mathit{dom}$と$\mathit{cod}$は、域と余域を「射」に割り当てる。 130 | 131 | このスパンをモナドにするには2つの$2$-セル$\eta$と$\mu$が必要だ。この場合のモノイドの単位元は、$\mathit{Ob}$から$\mathit{Ob}$への自明なスパンであり、頂点は$\mathit{Ob}$で、2つの恒等関数を伴う。$2$-セル$\eta$は頂点$\mathit{Ob}$と$\mathit{Arr}$との間の関数だ。つまり、$\eta$は「射」をすべての「対象」に割り当てる。$\cat{Span}$の$2$-セルは可換条件を満たす必要がある。ここでは次のようになる。 132 | $$ 133 | \begin{gathered} 134 | \mathit{dom} \circ \eta = \id \\ 135 | \mathit{cod} \circ \eta = \id 136 | \end{gathered} 137 | $$ 138 | 139 | `\begin{figure}[H] \centering`{=latex} 140 | ![](images/spanunit.png){width=40%} 141 | `\end{figure}`{=latex} 142 | 143 | \noindent 144 | 成分としては、これは次のようになる。 145 | $$\mathit{dom}\ (\eta\ \mathit{ob}) = \mathit{ob} = \mathit{cod}\ (\eta\ \mathit{ob})$$ 146 | ここで、$\mathit{ob}$は$\mathit{Ob}$内の「対象」だ。言い換えると、$\eta$はすべての「対象」に域と余域がその「対象」であるような「射」を割り当てる。この特別な「射」が「恒等射」と呼ばれる。 147 | 148 | 2番目の$2$-セル$\mu$は、スパン$\mathit{Arr}$のそれ自身との合成に作用する。合成は引き戻しとして定義されているため、その要素は$\mathit{Arr}$からの要素のペア――「射」のペア $(a_1, a_2)$ だ。引き戻し条件は次のとおりだ。 149 | $$\mathit{cod}\ a_1 = \mathit{dom}\ a_2$$ 150 | $a_2$と$a_1$が「合成可能」だと言うことにする。これは、一方の域が他方の余域だからだ。 151 | 152 | `\begin{figure}[H] \centering`{=latex} 153 | ![](images/spanmul.png){width=50%} 154 | `\end{figure}`{=latex} 155 | 156 | \noindent 157 | $2$-セル$\mu$は、合成可能な「射」のペア $(a_1, a_2)$ を、$\mathit{Arr}$からの単一の「射」$a_3$に写す関数だ。言い換えると、$\mu$は「射」の合成を定義する。 158 | 159 | モナド則が射の恒等律や結合律に対応していることは簡単に確認できる。以上で圏(対象と射が集合をなしている、小さい圏であることに注意)を定義できたことになる。 160 | 161 | つまり、まとめると、圏はスパンの双圏におけるモナドにすぎない。 162 | 163 | この結果の驚くべき点は、圏がモナドやモノイドのような他の代数的構造と同じ基盤に置かれていることだ。圏であることは何も特別ではない。ただの2つの集合と4つの関数だ。実際に、対象ごとに個別の集合さえ必要ない。対象は恒等射と同一視できる(それらは1対1で対応している)からだ。つまり、実際にはひとつの集合といくつかの関数にすぎない。圏論がすべての数学において中心的役割を担っていることを考えると、これにはとても謙虚な気持ちにさせられる。 164 | 165 | ## 課題 166 | 167 | 1. 双圏における自己-$1$-セルの合成として定義されたテンソル積について、単位律と結合律を導出せよ。 168 | 2. $\cat{Span}$内のモナドについて、モナド則が、結果の圏における恒等射と結合律に対応していることを確認せよ。 169 | 3. $\cat{Prof}$内のモナドが対象について恒等 (identity-on-object) な関手であることを示せ。 170 | 4. $\cat{Span}$内のモナドについてのモナド代数とは何か? 171 | 172 | ## 参考文献 173 | 174 | 1. [Paweł Sobocińskiのブログ](https://graphicallinearalgebra.net/2017/04/16/a-monoid-is-a-category-a-category-is-a-monad-a-monad-is-a-monoid/)^[] 175 | -------------------------------------------------------------------------------- /japanese/part1/ch03.md: -------------------------------------------------------------------------------- 1 | # 圏のさまざま 2 | 3 | さまざまな例を調べれば圏の真価が理解できる。圏にはさまざまな形やサイズがあり、予期しない場所によく現れる。ごくシンプルなものから始めよう。 4 | 5 | ## 対象がない場合 6 | 7 | 最も自明な圏は、対象が0個で、したがって射が0本のものだ。それ自体は非常に哀しい圏だが、他の圏との関連、たとえば、すべての圏の圏(そう、そういうものが存在する)において重要になるだろう。空集合に意味があると思うなら、空圏 (empty category) が無意味だとは思わないだろう? 8 | 9 | ## 有向グラフ 10 | 11 | 対象を射で接続するだけで圏を作成できる。任意の有向グラフから始めて、単に射を追加するだけで圏になるのは想像できるだろう。最初に、各ノードに恒等射を追加する。次に、一方の終点が他方の始点と一致するような2本の射(つまり、2つの[*合成可能な*]{.keyword #composable}\index{合成可能な}射)に対して、それらの合成として機能する新しい射を追加する。新しい射を追加するたびに、(恒等射を除く)他の射との合成も考慮する必要がある。たいていは射が無限に多くなるが、問題ない。 12 | 13 | このプロセスを別の方法で見ると、グラフ内の各ノードを対象とし、合成可能なグラフの辺からなるすべての[*チェイン*]{.keyword #chain}\index{チェイン}^[訳注:グラフ理論で歩道 (walk) と呼ばれるもの。]を射とする圏を作成していることになる。(恒等射はチェインの長さが0の特殊な場合とも見なせる。) 14 | 15 | このような圏は、与えられたグラフによって生成される[*自由圏*]{.keyword #free_category}\index{自由圏} (free category) と呼ばれる。これは自由構成 (free construction) の例であり、任意の構造を、その規則(ここでは圏の規則)を満たせる最少の項目で拡張して完成させるプロセスだ。今後さらに多くの例について見ていく。 16 | 17 | ## 順序 18 | 19 | さて、全く別のものを見てみよう! 射が対象間の関係、具体的には小なりイコール($\leqslant$)であるような圏だ。これが本当に圏かどうか調べてみよう。恒等射はあるだろうか? すべての対象はそれ自身以下だろうか? 良し! 合成はあるだろうか? $a \leqslant b$かつ$b \leqslant c$ならば$a \leqslant c$である。良し! 合成は結合的か? 良し! このような関係は[*前順序*]{.keyword #preorder}\index{前順序} (preorder) と呼ばれる。前順序は確かに圏だ。 20 | 21 | $a \leqslant b$かつ$b \leqslant a$ならば$a$は$b$と等しくなければならないという追加の条件も満たす、より強い関係も考えられる。これを[*半順序*]{.keyword #partial_order}\index{半順序} (partial order) と呼ぶ。 22 | 23 | 最後に、任意の2つの対象が$\leqslant$またはその逆で関係しているという条件も課せる。そうすると、[*線形順序*]{.keyword #linear_order}\index{線形順序} (linear order) または[*全順序*]{.keyword #total_order}\index{全順序} (total order) と呼ばれる関係が得られる。 24 | 25 | これらの関係を満たす順序集合を圏として特徴づけよう。前順序は、任意の対象$a$から任意の対象$b$に向かう射が高々1つ存在する圏となる。そのような圏は別名「細い圏」(thin category) と呼ばれる。前順序圏は細い圏だ。 26 | 27 | 圏$\cat{C}$における対象$a$から対象$b$への射の集合は[*hom集合*]{.keyword #hom-set}\index{hom集合}と呼ばれ^[訳注:後述のように、本書ではこれが一般には集合にならないということは敢えて無視している。]、$\cat{C}(a, b)$ と書かれる($\mathbf{Hom}_{\cat{C}}(a, b)$ とも書かれる)。したがって、前順序のhom集合はどれも空集合か単元集合になる。これはhom集合$\cat{C}(a, a)$、つまり$a$から$a$への射の集合にも当てはまる。その場合はどの前順序においても必ず単元集合になり、恒等射だけを含む。ただし、前順序では循環が起こり得る。半順序では循環は禁止されている。 28 | 29 | 整列(ソーティング)においては前順序・半順序・全順序を区別できることが非常に重要だ。クイックソート・バブルソート・マージソートなどの整列アルゴリズムは全順序に対してのみ正しく機能する。半順序にはトポロジカルソートが使える。 30 | 31 | ## 集合としてのモノイド 32 | 33 | モノイドは非常にシンプルにもかかわらず驚くほど強力な概念だ。それは基礎的な計算の背景にある概念であり、加算と乗算は両方ともモノイドをなす。モノイドはプログラミングの世界では至るところにある。それは、文字列、リスト、foldできるデータ構造、並行プログラミングのfuture、関数型リアクティブプログラミングのイベントなどとして現れる。 34 | 35 | 伝統的に、モノイドは二項演算を持つ集合として定義される。この演算に要求されるのは、結合律を満たすことと、単位元のように振る舞う特別な要素が1つあることだけだ。 36 | 37 | たとえば、0を含む自然数は加算についてモノイドをなす。結合律は次のことを意味する。 38 | $$(a + b) + c = a + (b + c)$$ 39 | (言い換えると、数を加算するときは括弧を無視できる。) 40 | 41 | 中立元^[訳注:単位元に同じ。]は0だ。なぜなら 42 | $$0 + a = a$$ 43 | かつ 44 | $$a + 0 = a$$ 45 | だからだ。2つ目の等式は冗長だ。加算は可換 $(a + b = b + a)$ だからだ。ただし、可換律はモノイドの定義の一部ではない。たとえば、文字列連接は可換ではないが、モノイドをなす。ちなみに、文字列連接の中立元は空文字列であり、文字列を変更せずに文字列の両側に付加できる。 46 | 47 | Haskellではモノイドに対して型クラスを定義できる。その型クラスに属する型は、`mempty`と呼ばれる中立元と`mappend`と呼ばれる二項演算を持つ^[訳注:現在のHaskellでは`Monoid`は`Semigroup`の派生クラス。`Semigroup`では`(<>) :: a -> a -> a`が定義されており、`Monoid`で`mappend = (<>)`以外の定義をすると警告が表示される。`mapppend`は将来廃止される予定。]。 48 | 49 | ```haskell 50 | class Monoid m where 51 | mempty :: m 52 | mappend :: m -> m -> m 53 | ``` 54 | 55 | \noindent 56 | この2引数関数の型シグネチャーでの`m -> m -> m`という型は、最初は奇妙に見えるかもしれないが、カリー化を知った後には完全に理にかなったものだと思えるようになるだろう。複数の矢印を含むシグネチャーには、2つの基本的な解釈がある。複数の引数を取る関数とみなして右端の型を戻り値の型とする解釈と、1引数(左端の引数)の関数とみなして関数を返すという解釈だ。後者の解釈は、`m -> (m -> m)`のように括弧(矢印が右結合であるため冗長)を追加することによって強調できる。この解釈については後で説明する。 57 | 58 | Haskellでは、`mempty`と`mappend`のモノイド性(monoidal 59 | properties、すなわち、`mempty`は中立で、`mappend`は結合律を満たすという事実)を表現する方法がないことに注意してほしい。それらを満たすことを確認するのはプログラマーの責任だ。 60 | 61 | HaskellのクラスはC++のクラスほど押し付けがましくはない。新しい型を定義するときに事前にクラスを指定する必要はない。先延ばしして、与えられた型を後からあるクラスのインスタンスであると宣言してよい。例として、`mempty`と`mappend`の実装を提供することで`String`をモノイドとして宣言しよう(実際には、これは標準のPreludeですでにやってくれている)。 62 | 63 | ```haskell 64 | instance Monoid String where 65 | mempty = "" 66 | mappend = (++) 67 | ``` 68 | 69 | \noindent 70 | ここで、`String`の値は単に文字のリストなので、リスト連接演算子`(++)`を再利用した。 71 | 72 | Haskellの構文に関する注:中置演算子は括弧で囲うことで2つの引数を取る関数に変換できる。与えられた2つの文字列を連接するには、それらの間に`++`を挟んでもよい。 73 | 74 | ```haskell 75 | "Hello " ++ "world!" 76 | ``` 77 | 78 | \noindent 79 | あるいは、括弧付きの`(++)`に2つの文字列を引数として渡してもよい。 80 | 81 | ```haskell 82 | (++) "Hello " "world!" 83 | ``` 84 | 85 | \noindent 86 | 関数の引数がコンマで区切られたり括弧で囲まれたりしていないことに注意してほしい。(これはおそらく、Haskellを学ぶときに慣れるのが一番難しい部分だろう。) 87 | 88 | Haskellでは関数の等しさを次のように表現できることは、強調しておく価値がある。 89 | 90 | ```haskell 91 | mappend = (++) 92 | ``` 93 | 94 | \noindent 95 | 概念的には、これは関数によって生成される値の等しさを次のように表現するのとは異なる。 96 | 97 | ```haskell 98 | mappend s1 s2 = (++) s1 s2 99 | ``` 100 | 101 | \noindent 102 | 前者は、$\Hask$圏(または、終わりのない計算を指すボトムを無視するなら、$\Set$)の射の等しさに変換される。このような等式はより簡潔であるだけでなく、しばしば他の圏にも一般化できる。後者は[*外延的*]{.keyword #extensional}\index{外延的}等価性 (extensional equivalence) と呼ばれ、どんな2つの入力文字列に対しても`mappend`と`(++)`の出力は同じであることを述べている。引数の値は[*点*]{.keyword #point}\index{点} (point) と呼ばれることが(「点$x$における$f$の値」という言い回しのように)あるため、これは点ごとの等しさ (point-wise equality) と呼ばれる。引数を指定しない関数の等しさは[*ポイントフリー*]{.keyword #point-free}\index{ポイントフリー} (point-free) と表現される。(ちなみに、ポイントフリーの式は関数合成を含むことが多く、これは点記号`.`で表されるため、初心者は少し混乱するかもしれない。) 103 | 104 | C++でモノイドを宣言するのに最も近い方法は、C++20標準のコンセプト機能を使うことだ。 105 | 106 | ```cpp 107 | template 108 | struct mempty; 109 | 110 | template 111 | T mappend(T, T) = delete; 112 | 113 | template 114 | concept Monoid = requires (M m) { 115 | { mempty::value() } -> std::same_as; 116 | { mappend(m, m); } -> std::same_as; 117 | }; 118 | ``` 119 | 120 | \noindent 121 | 最初の定義は、各特殊化で中立元を保持するための構造だ。 122 | 123 | キーワード`delete`は、デフォルト値が定義されていないことを意味する。これはケースバイケースで指定する必要がある。同様に、`mappend`にもデフォルトはない。 124 | 125 | `Monoid`というコンセプトは、与えられた型`M`に対して`mempty`と`mappend`の適切な定義が存在するかをテストする。 126 | 127 | このMonoidコンセプトのインスタンス化は、適切な特殊化とオーバーロードを提供することで実現できる。 128 | 129 | ```cpp 130 | template<> 131 | struct mempty { 132 | static std::string value() { return ""; } 133 | }; 134 | 135 | template<> 136 | std::string mappend(std::string s1, std::string s2) { 137 | return s1 + s2; 138 | } 139 | ``` 140 | 141 | ## 圏としてのモノイド {#monoid-as-set} 142 | 143 | ここまではモノイドの「おなじみの」定義として、集合の要素に基づくものを見た。しかし、ご存知のように、圏論では集合とその要素から逃れようとし、代わりに対象と射について述べる。そこで、少し視点を変えて、二項演算子を適用すると集合の周りで何かを「移動」したり「シフト」したりすると考えてみよう。 144 | 145 | たとえば、各自然数に5を加算する演算を考える。これは0を5、1を6 、2を7のように写す。これは関数で、自然数の集合上で定義されている。良い感じだ。関数と集合がある。一般に、任意の数$n$について、$n$を加算する関数が存在する。これは$n$の「加算器」だ。 146 | 147 | 加算器はどのように合成すればよいだろう? 5を加算する関数と7を加算する関数の合成は、12を加算する関数だ。これにより、加算器の合成を加算ルールと等価にできる。これまた良い感じだ。加算を関数合成に置き換えられる。 148 | 149 | ちょっと待った。それだけではない。中立元0の加算器もある。0を加算しても何も写されないので、これは自然数の集合における恒等関数だ。 150 | 151 | 従来の加算の規則を与える代わりに、情報を失うことなく加算器を構成する規則を与えることもできる。加算器の合成は結合律を満たすことに注目してほしい。これは、関数の合成が結合律を満たし、恒等関数に対応する0加算器があるからだ。 152 | 153 | 鋭い読者なら、整数から加算器への写像が`mappend`の型シグネチャーを`m -> (m -> m)`と解釈した結果であることに気付いただろう。これは`mappend`がモノイド集合の要素を、その集合に作用する関数に写すことを表している。 154 | 155 | さて、自然数の集合を扱っていることを忘れて、たくさんの射――加算器たちをひとかたまりにした、単一の対象だと考えてほしい。モノイドは単一対象の圏だ。実際、monoidという名前は、ギリシャ語で単一を意味する*mono*に由来する。すべてのモノイドは、適切な合成規則に従う射の集合を持つ単一対象の圏として表せる。 156 | 157 | `\begin{figure}[H] \centering`{=latex} 158 | ![](images/monoid.jpg){width=35%} 159 | `\end{figure}`{=latex} 160 | 161 | \noindent 162 | 文字列の連接は興味深いケースだ。なぜなら、右連接器(right appender)と左連接器(left appender、あるいはお好みなら前置器prepender)^[訳注:appendは後ろにくっつけることなので、前(左)にappendするのは英語話者には違和感があるのだろう。]を定義する選択肢があるからだ。2つのモデルの合成表は互いに鏡像反転している。「foo」に「bar」を後置するのと「bar」に「foo」を前置するのが同じなのは簡単に納得できるだろう。 163 | 164 | 圏論的モノイド――単一対象の圏――はどれも二項演算を伴う集合としてのモノイドを一意に定義するのか、という疑問を持つかもしれない。単一対象の圏からは常に集合を抽出できることが分かる。その集合は射――この例では加算器――の集合だ。言い換えれば、圏$\cat{M}$内の単一対象$m$についてhom集合$\cat{M}(m, m)$ が得られるということだ。この集合における二項演算は簡単に定義できる。2つの集合要素のモノイド的な積は、それらに対応する射を合成したものに対応する要素だ。つまり、$\cat{M}(m, m)$ の2つの要素が与えられ、それらに対応する射が$f$と$g$だとすると、それらの積は合成$f \circ g$に対応する要素となる。この合成は常に存在する。なぜなら、射の始点と終点が同じ対象だからだ。また、圏の規則より、結合律も満たす。恒等射はこの積の中立元だ。このように、圏論的モノイドからは常に集合論的モノイドを復元できる。どこからどう見てもそれらは同一だ。 165 | 166 | ![射あるいは集合内の点として見たモノイドhom集合](images/monoidhomset.jpg "射あるいは集合内の点として見たモノイドhom集合"){width=40%} 167 | 168 | \noindent 169 | 数学者が補足すべき箇所は、射は必ずしも集合をなさないということだけだ。圏の世界には集合よりも大きなものがある。任意の2つの対象間の射が集合をなす圏は、局所的に小さい、と呼ばれる。約束どおり、私はそのような些細なことはほとんど無視するが、念のため言及すべきだと考えた。 170 | 171 | hom集合の要素は、合成律に従う射とも、ある集合内の点とも見なせる。圏論における多くの興味深い現象はこの事実に根ざしている。ここで、$\cat{M}$の射の合成は、集合$\cat{M}(m, m)$ でのモノイド的な積に変換される。 172 | 173 | ## 課題 174 | 175 | 1. 以下から自由圏を生成せよ。 176 | 1. 1つのノードを持ち、辺のないグラフ 177 | 1. 1つのノードと1つの(有向)辺を持つグラフ(ヒント:この辺は自身と合成できる) 178 | 1. 2つのノードと、それらの間の(有向)辺を1つ持つグラフ 179 | 1. 1つのノードと、アルファベットa, b, c $\ldots$ zでマークされた26個の(有向)辺を持つグラフ 180 | 181 | 1. 以下はどんな順序だろうか? 182 | 1. 複数の集合を要素とする集合と、その上の包含関係。なお、$A$が$B$に包含されるとは、$A$の全要素が$B$の要素でもあることを指す。 183 | 1. C++の型の集合とその上の部分型関係。なお、`T1`が`T2`の部分型であるとは、`T2`へのポインターを期待する関数に`T1`をコンパイルエラーを発生させずに渡せることを指す。 184 | 185 | 1. `Bool`が2つの値`True`と`False`の集合であることを踏まえて、それが2つの演算子`&&` (AND) と`||` (OR) のそれぞれについて(集合論的)モノイドをなすことを示せ。 186 | 187 | 1. AND演算子を伴う`Bool`モノイドを圏として表せ。射と合成の規則を列挙せよ。 188 | 189 | 1. モジュロ3加算^[訳注:加算して3で割った余りを取る演算。]をモノイドの圏として表せ。 190 | -------------------------------------------------------------------------------- /english/preface.md: -------------------------------------------------------------------------------- 1 | \clearpage 2 | 3 | # Preface {-} 4 | 5 | > 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.^[You may also watch me teach this material to a live audience, at (or search ``bartosz milewski category theory'' on YouTube.)] 6 | 7 | \vskip1\baselineskip 8 | 9 | I will attempt, in the space of a few paragraphs, to convince you that this book is written for you, and whatever objections you might have to learning one of the most abstract branches of mathematics in your “copious spare time” are totally unfounded. 10 | 11 | My optimism is based on several observations. First, category theory is a treasure trove of extremely useful programming ideas. Haskell programmers have been tapping this resource for a long time, and the ideas are slowly percolating into other languages, but this process is too slow. We need to speed it up. 12 | 13 | Second, there are many different kinds of math, and they appeal to different audiences. You might be allergic to calculus or algebra, but it doesn’t mean you won’t enjoy category theory. I would go as far as to argue that category theory is the kind of math that is particularly well suited for the minds of programmers. That’s because category theory — rather than dealing with particulars — deals with structure. It deals with the kind of structure that makes programs composable. 14 | 15 | Composition is at the very root of category theory — it’s part of the definition of the category itself. And I will argue strongly that composition is the essence of programming. We’ve been composing things forever, long before some great engineer came up with the idea of a subroutine. Some time ago the principles of structured programming revolutionized programming because they made blocks of code composable. Then came object oriented programming, which is all about composing objects. Functional programming is not only about composing functions and algebraic data structures — it makes concurrency composable — something that’s virtually impossible with other programming paradigms. 16 | 17 | Third, I have a secret weapon, a butcher’s knife, with which I will butcher math to make it more palatable to programmers. When you’re a professional mathematician, you have to be very careful to get all your assumptions straight, qualify every statement properly, and construct all your proofs rigorously. This makes mathematical papers and books extremely hard to read for an outsider. I’m a physicist by training, and in physics we made amazing advances using informal reasoning. Mathematicians laughed at the Dirac delta function, which was made up on the spot by the great physicist P. A. M. Dirac to solve some differential equations. They stopped laughing when they discovered a completely new branch of calculus called distribution theory that formalized Dirac’s insights. 18 | 19 | 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 Category Theory for the Working Mathematician on my nightstand. 20 | 21 | Since this is category theory for programmers I will illustrate all major concepts using computer code. You are probably aware that functional languages are closer to math than the more popular imperative languages. They also offer more abstracting power. So a natural temptation would be to say: You must learn Haskell before the bounty of category theory becomes available to you. But that would imply that category theory has no application outside of functional programming and that’s simply not true. So I will provide a lot of C++ examples. Granted, you’ll have to overcome some ugly syntax, the patterns might not stand out from the background of verbosity, and you might be forced to do some copy and paste in lieu of higher abstraction, but that’s just the lot of a C++ programmer. 22 | 23 | But you’re not off the hook as far as Haskell is concerned. You don’t have to become a Haskell programmer, but you need it as a language for sketching and documenting ideas to be implemented in C++. That’s exactly how I got started with Haskell. I found its terse syntax and powerful type system a great help in understanding and implementing C++ templates, data structures, and algorithms. But since I can’t expect the readers to already know Haskell, I will introduce it slowly and explain everything as I go. 24 | 25 | If you’re an experienced programmer, you might be asking yourself: I’ve been coding for so long without worrying about category theory or functional methods, so what’s changed? Surely you can’t help but notice that there’s been a steady stream of new functional features invading imperative languages. Even Java, the bastion of object-oriented programming, let the lambdas in. C++ has recently been evolving at a frantic pace — a new standard every few years — trying to catch up with the changing world. All this activity is in preparation for a disruptive change or, as we physicist call it, a phase transition. If you keep heating water, it will eventually start boiling. We are now in the position of a frog that must decide if it should continue swimming in increasingly hot water, or start looking for some alternatives. 26 | 27 | `\begin{figure}[H] \centering`{=latex} 28 | ![](images/img_1299.jpg){width=50%} 29 | `\end{figure}`{=latex} 30 | \noindent 31 | One of the forces that are driving the big change is the multicore revolution. The prevailing programming paradigm, object oriented programming, doesn’t buy you anything in the realm of concurrency and parallelism, and instead encourages dangerous and buggy design. Data hiding, the basic premise of object orientation, when combined with sharing and mutation, becomes a recipe for data races. The idea of combining a mutex with the data it protects is nice but, unfortunately, locks don’t compose, and lock hiding makes deadlocks more likely and harder to debug. 32 | 33 | But even in the absence of concurrency, the growing complexity of software systems is testing the limits of scalability of the imperative paradigm. To put it simply, side effects are getting out of hand. Granted, functions that have side effects are often convenient and easy to write. Their effects can in principle be encoded in their names and in the comments. A function called SetPassword or WriteFile is obviously mutating some state and generating side effects, and we are used to dealing with that. It’s only when we start composing functions that have side effects on top of other functions that have side effects, and so on, that things start getting hairy. It’s not that side effects are inherently bad — it’s the fact that they are hidden from view that makes them impossible to manage at larger scales. Side effects don’t scale, and imperative programming is all about side effects. 34 | 35 | Changes in hardware and the growing complexity of software are forcing 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 [cathedral in Beauvais](https://en.wikipedia.org/wiki/Beauvais_Cathedral)^[], 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 obviously a lot of things went wrong. From a modern perspective, it’s a miracle that so many gothic structures had been successfully completed without the help of modern material science, computer modelling, finite element analysis, and general math and physics. I hope future generations will be as admiring of the programming skills we’ve been displaying in building complex operating systems, web servers, and the internet infrastructure. And, frankly, they should, because we’ve done all this based on very flimsy theoretical foundations. We have to fix those foundations if we want to move forward. 36 | 37 | ![Ad hoc measures preventing the Beauvais cathedral from collapsing](images/beauvais_interior_supports.jpg "Ad hoc measures preventing the Beauvais cathedral from collapsing"){width=50%} 38 | -------------------------------------------------------------------------------- /japanese/part2/ch05.md: -------------------------------------------------------------------------------- 1 | # 米田の補題 {#the-yoneda-lemma} 2 | 3 | 圏論における構成物のほとんどは、より具体的な他の数学の分野での結果を一般化したものだ。積・余積・モノイド・冪などは、圏論よりずっと前から知られていた。それらは別の数学の分野では別の名前で知られていたかもしれない。集合論におけるデカルト積、順序理論における交わり (meet)、論理学における論理積――これらはすべて圏論的な積という抽象概念に対応する具体例だ。 4 | 5 | 米田の補題は、この観点から、数学の他の分野では全くと言ってよいほど前例がないような圏一般に関する包括的な主張として際立っている。一番似ているのは群論におけるケイリーの定理(すべての群はある集合の置換群と同型)^[監訳注:詳細は省くが、群の要素$x$を$y \mapsto x \otimes y$という関数に写すような写像を考えると、これが実は単射な準同型写像になっていて像も部分群になっている。同様の写像は、モノイドについて、関数プログラミングにおける差分リストの表現(Hughesのリスト表現)でも用いられる。また、(こちらもモノイドについての)16章の章末課題3も参照。]だという説もある。 6 | 7 | 米田の補題の問題設定は、$\Set$への関手$F$を持つような任意の圏$\cat{C}$についてのものだ。すでに前章で述べたように、集合値関手のいくつかは表現可能、つまりhom関手と同型である。米田の補題は、すべての集合値関手がhom関手たちから自然変換によって得られることを示し、そのようなすべての変換を明示的に列挙する。 8 | 9 | 自然変換について話したとき、自然性条件は制限が非常に強いものになる場合があると述べた。1つの対象における自然変換の成分を定義するとき、射を介して接続されている別の対象へとその成分を「トランスポート」できるほどに自然性が強いことがある。もとの圏と行き先の圏で対象間の射が多いほど、自然変換の成分をトランスポートするための制約が厳しくなる。$\Set$はたまたま射が豊富な圏だ。 10 | 11 | 米田の補題から言えるのは、あるhom関手と他の任意の関手$F$との間の自然変換が、その単一成分の値をある1点について指定するだけで完全に決定されるということだ! 残りの成分は単に自然性条件に従って決まる。 12 | 13 | では、米田の補題に関わる2つの関手について、その間の自然性条件をおさらいしよう。1番目の関手はhom関手だ。それは$\cat{C}$内の任意の対象$x$を射の集合$\cat{C}(a, x)$ に写す。ここで、$a$は$\cat{C}$内の固定された対象だ。また、すでに見たとおり、そのhom関手は$x$から$y$への射$f$をすべて$\cat{C}(a, f)$ に写す。 14 | 15 | 2番目の関手は任意の集合値関手$F$だ。 16 | 17 | この2つの関手の間の自然変換を$\alpha$と呼ぶことにしよう。$\Set$内を扱っているので、$\alpha_x$や$\alpha_y$などの自然変換の成分は集合間の通常の関数にすぎない。 18 | $$ 19 | \begin{gathered} 20 | \alpha_x \Colon \cat{C}(a, x) \to F x \\ 21 | \alpha_y \Colon \cat{C}(a, y) \to F y 22 | \end{gathered} 23 | $$ 24 | 25 | `\begin{figure}[H] \centering`{=latex} 26 | ![](images/yoneda1.png){width=40%} 27 | `\end{figure}`{=latex} 28 | 29 | \noindent 30 | そして、これらは単なる関数なので、特定の点での値を見られる。だが、集合$\cat{C}(a, x)$ 内の点とは何だろうか? 鍵となる観察はこうだ。集合$\cat{C}(a, x)$ 内のすべての点は、$a$から$x$への射$h$でもある。 31 | 32 | したがって、$\alpha$についての自然性の正方図式 33 | $$\alpha_y \circ \cat{C}(a, f) = F f \circ \alpha_x$$ 34 | の両辺を$h$に作用させると、点ごとの等式になる。 35 | $$\alpha_y (\cat{C}(a, f) h) = (F f) (\alpha_x h)$$ 36 | 前の節でhom関手$\cat{C}(a, -)$ の射$f$への作用を、次のような前合成として定義したことを思い出しただろう。 37 | $$\cat{C}(a, f) h = f \circ h$$ 38 | これにより次が導かれる。 39 | $$\alpha_y (f \circ h) = (F f) (\alpha_x h)$$ 40 | この条件がどれほど強いかは$x = a$の場合に特化させれば分かる。 41 | 42 | `\begin{figure}[H] \centering`{=latex} 43 | ![](images/yoneda2.png){width=40%} 44 | `\end{figure}`{=latex} 45 | 46 | \noindent 47 | この場合、$h$は$a$から$a$への射となる。そのような射が少なくとも1つ存在するのは分かっている。$h = \id_a$だ。これを代入してみよう。 48 | $$\alpha_y f = (F f) (\alpha_a \id_a)$$ 49 | 何が起きたか注目してほしい。左辺は$\alpha_y$を$\cat{C}(a, y)$ の任意の要素$f$に作用させている。そして、その結果は$\id_a$における$\alpha_a$という単一の値によって完全に決まる。そのような値は任意に選べて、それによって自然変換が生成される。$\alpha_a$たちの値は集合$F a$に含まれるので、$F a$のどの点からも何らかの$\alpha$が定義される。 50 | 51 | 逆に、$\cat{C}(a, -)$ から$F$への自然変換$\alpha$が与えられた場合、$\id_a$において評価すれば$F a$の点を得られる。 52 | 53 | 以上より、米田の補題が証明された。 54 | 55 | > $\cat{C}(a, -)$ から$F$への自然変換と$F a$の要素との間には1対1の対応がある。 56 | 57 | 言い換えれば 58 | $$\Nat(\cat{C}(a, -), F) \cong F a$$ 59 | となる。あるいは、$[\cat{C}, \Set]$という表記で$\cat{C}$と$\Set$の間の関手圏を表すと、自然変換の集合は単にその圏のhom集合であり、次のように書ける。 60 | $$[\cat{C}, \Set](\cat{C}(a, -), F) \cong F a$$ 61 | この対応が実際には自然同型である仕組みについては後で説明する。 62 | 63 | さて、この結果について直観的に理解してみよう。最も驚くべきことは、自然変換全体の結晶化が、$\id_a$において割り当てた値というたった1粒の種から始まることだ。結晶化はその1点から自然性条件に従って広がっていく。そして$\Set$内に$\cat{C}$の像を溢れさせる。そこで、まずは$\cat{C}(a, -)$ の下で$\cat{C}$の像について考えてみたい。 64 | 65 | $a$自体の像から始めよう。$a$は、hom関手$\cat{C}(a, -)$ の下では集合$\cat{C}(a, a)$ に写される。一方、関手$F$の下では集合$F a$に写される。自然変換の成分$\alpha_a$は、$\cat{C}(a, a)$ から$F a$への何らかの関数となる。集合$\cat{C}(a, a)$ の中の1点だけに注目することにしよう。具体的には射$\id_a$に対応する点だ。集合内の1点にすぎないという事実を強調するために、それを$p$と呼ぼう。成分$\alpha_a$は$p$を$F a$内のある点$q$に写すはずだ。どんな$q$を選択しても一意な自然変換が得られることを説明しよう。 66 | 67 | `\begin{figure}[H] \centering`{=latex} 68 | ![](images/yoneda3.png){width=30%} 69 | `\end{figure}`{=latex} 70 | 71 | \noindent 72 | 1つ目の主張は、1点$q$を選択すれば関数$\alpha_a$の残りが一意に決まる、というものだ。実際に、$a$から$a$へのある射$g$に対応する他の任意の点$p'$を$\cat{C}(a, a)$ 内で選んでみよう。ここで米田の補題の魔法が起こり、$g$は集合$\cat{C}(a, a)$ 内の点$p'$と見なせる。同時に、それは集合間の2つの*関数*を選択する。確かに射$g$は、hom関手では関数$\cat{C}(a, g)$ に写され、$F$では$F g$に写される。 73 | 74 | `\begin{figure}[H] \centering`{=latex} 75 | ![](images/yoneda4.png){width=40%} 76 | `\end{figure}`{=latex} 77 | 78 | \noindent 79 | ここで、もとの$p$に対する$\cat{C}(a, g)$ の作用を考えてみよう。覚えているとおり、$p$は$\id_a$に対応する。それは前合成$g \circ \id_a$として定義され、$g$と同じであり、点$p'$に対応する。したがって、射$g$は、$p$に作用すると$p'$、すなわち$g$を生成するような関数に写される。ぐるりと一周した! 80 | 81 | さて、$q$に対する$F g$の作用を考えてみよう。これは$F a$内のある点$q'$となる。自然性の正方図式^[訳注:$\alpha_a \circ \cat{C}(a, g) = F g \circ \alpha_a$を$p = \id_a$に作用させたもの。いま、$\cat{C}(a, g) p = g$であり、$p' = g$とおいていたので、左辺が$\alpha_a p'$となり、また$q = \alpha_a p$であったので、右辺が$F g (\alpha_a p) = F g q = q'$となる。]を完成させるには、$p'$が$\alpha_a$によって$q'$に写される必要がある。 82 | 任意の$p'$(任意の$g$)を選択し、$\alpha_a$の下でのその写し先^[訳注:$q'$、すなわち$F g q$のこと。]を導出した。したがって、関数$\alpha_a$は完全に決定される。 83 | 84 | 2つ目の主張は、$\cat{C}$内で$a$に接続された対象$x$に対して$\alpha_x$が一意に決定される、というものだ。これも同様の論法による。ただし、ここではさらに2つの集合$\cat{C}(a, x)$ と$F x$があり、$a$から$x$への[訳注:任意に選んだ]射$g$は、hom関手の下では 85 | $$\cat{C}(a, g) \Colon \cat{C}(a, a) \to \cat{C}(a, x)$$ 86 | に写され、$F$の下では 87 | $$F g \Colon F a \to F x$$ 88 | に写される。ここでも、$p$に作用した場合の$\cat{C}(a, g)$ は前合成$g \circ \id_a$によって与えられ、$\cat{C}(a, x)$ 内の点$p'$となる。自然性により、$p'$に作用する$\alpha_x$の値はこう決まる。 89 | $$q' = (F g) q$$ 90 | $p'$は任意に決めていたので、関数$\alpha_x$全体が決定される。 91 | 92 | `\begin{figure}[H] \centering`{=latex} 93 | ![](images/yoneda5.png){width=40%} 94 | `\end{figure}`{=latex} 95 | 96 | \noindent 97 | $\cat{C}$内に$a$と接続されていない対象がある場合はどうなるだろう? それらすべてが$\cat{C}(a, -)$ の下で空集合に写される。空集合は集合の圏における始対象であることを思い出してほしい。これは、この集合から他のどの集合へも一意な関数があることを意味する。その関数を`absurd`と呼んだ。したがって、ここでも自然変換の成分には選択の余地がなく、`absurd`しかあり得ない。 98 | 99 | 米田の補題を理解する方法の1つは、集合値関手の間の自然変換は関数の族にすぎず、関数は一般には非可逆だと気付くことだ。関数は情報を潰すこともあり、余域の一部しかカバーしないこともある。非可逆でない関数は、可逆なもの、つまり同型たちだけだ。したがって、構造を保存する最も優れた集合値関手たちは表現可能関手だということになる。それらはhom関手か、あるいはhom関手と自然同型な関手のどちらかだ。その他の関手$F$はすべてhom関手を非可逆変換することで得られる。そのような変換は、情報を失わせるだけでなく、関手$F$による$\Set$内の像のごく一部しかカバーしない可能性がある。 100 | 101 | ## Haskellにおける米田の補題 102 | 103 | Haskellのhom関手には、すでにreader関手という名前で出会っている。 104 | 105 | ```haskell 106 | type Reader a x = a -> x 107 | ``` 108 | 109 | \noindent 110 | Readerは射たち(ここでは関数たち)を前合成で写す。 111 | 112 | ```haskell 113 | instance Functor (Reader a) where 114 | fmap f h = f . h 115 | ``` 116 | 117 | \noindent 118 | 米田の補題によれば、reader関手は他の任意の関手へ自然に写せる。 119 | 120 | 自然変換は多相関数だ。さて、任意の関手`F`について、reader関手からの写像を考えられる。 121 | 122 | ```haskell 123 | alpha :: forall x . (a -> x) -> F x 124 | ``` 125 | 126 | \noindent 127 | いつものように、`forall`は必須ではないが、自然変換のパラメトリック多相性を強調するために明示的に書くことにしている。 128 | 129 | 米田の補題によれば、これらの自然変換は`F a`の要素たちと1対1に対応している。 130 | 131 | ```haskell 132 | forall x . (a -> x) -> F x ≅ F a 133 | ``` 134 | 135 | \noindent 136 | この等式の右辺は、通常はデータ構造と見なしているものだった。一般化されたコンテナーとして関手を解釈したのを覚えているだろうか? `F a`は`a`のコンテナーだ。一方で、左辺は関数を引数に取る多相関数だ。米田の補題によれば、この2つの表現は等価だ――それらは同じ情報を含んでいる。 137 | 138 | 別の言い方をすると以下のようになる。次のような型の多相関数 139 | 140 | ```haskell 141 | alpha :: forall x . (a -> x) -> F x 142 | ``` 143 | 144 | \noindent 145 | を与えてくれれば`a`のコンテナーを作成してみせよう。ここで使うトリックは米田の補題の証明で使ったものだ。つまり、この関数を`id`で呼び出すことで型`F a`の要素を得る。 146 | 147 | ```haskell 148 | alpha id :: F a 149 | ``` 150 | 151 | \noindent 152 | 逆もまた真だ。型`F a`の任意の値 153 | 154 | ```haskell 155 | fa :: F a 156 | ``` 157 | 158 | \noindent 159 | について、適切な型の多相関数 160 | 161 | ```haskell 162 | alpha h = fmap h fa 163 | ``` 164 | 165 | \noindent 166 | を定義できる。2つの表現の間は簡単に行き来できるということだ。 167 | 168 | 表現が複数ある利点は、一方が他方よりも合成しやすかったり、用途によってはより効率的だったりすることだ。 169 | 170 | この原則の最も単純な例は、コンパイラーの構成でよく使われるコード変換である、継続渡し形式 (continuation passing style, CPS) だ。これは米田の補題を恒等関手へ最も単純に適用したものだ。`F`を恒等関手に置き換えると、次のようになる。 171 | 172 | ```haskell 173 | forall r . (a -> r) -> r ≅ a 174 | ``` 175 | 176 | \noindent 177 | この等式は、任意の型`a`は`a`に対する「ハンドラー」を取る関数によって置き換えられる、と解釈できる。ハンドラーは、`a`を受け入れ、残りの計算――継続――を実行する関数だ。(型`r`は通常、ある種のステータスコードをカプセル化している。) 178 | 179 | このスタイルのプログラミングは、UI、非同期システム、並行プログラミングではごく一般的だ。CPSの欠点は、制御の反転を伴うことだ。コードが生産者と消費者(ハンドラー)に分割され、簡単には合成できない。ウェブプログラミングの経験がある人なら誰でも、ステートフルなハンドラーとやり取りするスパゲッティコードの悪夢をよく知っている^[訳注:2026年現在では、そういった処理を直接書くことは`async`/`await`などによって少なくなったかもしれない。]。後で見るように、関手とモナドを慎重に使えばCPSの合成的な特性をいくらか取り戻せる。 180 | 181 | ## 余米田の補題 182 | 183 | いつものように、射の方向を逆にすればおまけの構成が得られる。米田の補題を反対圏$\cat{C}^\mathit{op}$に適用すれば反変関手の間の写像が得られる。 184 | 185 | 同様に、hom関手の始点となる対象の代わりに終点となる対象を固定することで、余米田の補題を導出できる。$\cat{C}$から$\Set$への反変hom関手を取れる。すなわち$\cat{C}(-, a)$ である。反変版の米田の補題は、この関手から他の任意の反変関手$F$への自然変換と、集合$F a$の要素との間に1対1の対応を確立する。 186 | $$\cat{Nat}(\cat{C}(-, a), F) \cong F a$$ 187 | Haskell版の余米田の補題は次のようになる。 188 | 189 | ```haskell 190 | forall x . (x -> a) -> F x ≅ F a 191 | ``` 192 | 193 | \noindent 194 | 一部の文献では反変版の方を米田の補題と呼んでいるので注意してほしい。 195 | 196 | ## 課題 197 | 198 | 1. 米田の同型をなす2つのHaskellの関数`phi`と`psi`が互いに逆であることを示せ。 199 | 200 | ```haskell 201 | phi :: (forall x . (a -> x) -> F x) -> F a 202 | phi alpha = alpha id 203 | 204 | psi :: F a -> (forall x . (a -> x) -> F x) 205 | psi fa h = fmap h fa 206 | ``` 207 | 208 | 1. 離散圏 (discrete category) は、対象はあるが恒等射以外の射はない圏だ。米田の補題はそのような圏の関手でどのように役立つだろうか? 209 | 210 | 1. unit型のリスト`[()]`は長さ以外の情報を含まない。したがって、データ型としては、非負整数を表したものと見なせる。空リストは0を表し、単リスト`[()]`(型ではなく値)は1を表し、以下同様だ。このデータ型の別の表現を、リスト関手に対する米田の補題を使って構成せよ。 211 | 212 | ## 参考文献 213 | 214 | 1. [Catstersの動画](https://www.youtube.com/watch?v=TLMxHB19khE)^[] 215 | -------------------------------------------------------------------------------- /japanese/part2/ch06.md: -------------------------------------------------------------------------------- 1 | # 米田埋め込み {#yoneda-embedding} 2 | 3 | 以前見たとおり、圏$\cat{C}$について対象$a$を固定すると、写像$\cat{C}(a, -)$ は$\cat{C}$から$\Set$への(共変)関手となる。 4 | $$x \to \cat{C}(a, x)$$ 5 | (Hom集合$\cat{C}(a, x)$ は*集合*なのでこの関手の余域は$\Set$だ。) 6 | この写像はhom関手と呼ばれる。射に対するこの関手の作用についてもすでに定義したことを思い出してほしい。 7 | 8 | さて、この写像において$a$を変化させてみよう。すると、Hom*関手*$\cat{C}(a, -)$ を任意の$a$に対して割り当てる新しい写像が得られる。 9 | $$a \to \cat{C}(a, -)$$ 10 | これは圏$\cat{C}$の対象たちから関手たち、すなわち関手圏の*対象*たちへの写像である(関手圏については[自然変換](#natural-transformations)(第10章3節) 11 | を参照)。$\cat{C}$から$\Set$への関手圏を$[\cat{C}, \Set]$と表記しよう。また、覚えているかもしれないが、Hom関手は[表現可能関手](#representable-functors)(第14章)の原型だった。 12 | 13 | 2つの圏の間に対象の写像があるのを見るたび、そのような写像が関手でもあるかを問うのは自然なことだ。言い換えると、一方の圏の射をもう一方の圏の射へと持ち上げられるか、ということだ。$\cat{C}$の射は$\cat{C}(a, b)$ の要素にすぎないが、関手圏$[\cat{C}, \Set]$の射は自然変換だ。つまり、ここでは射から自然変換への写像を探していることになる。 14 | 15 | 射$f \Colon a \to b$に対応する自然変換が見つかるか見てみよう。そのため、まず$a$と$b$が何に写されるか見てみよう。それらは2つの関手$\cat{C}(a, -)$ と$\cat{C}(b, -)$ に写される。求めるものは、これら2つの関手の間の自然変換だ。 16 | 17 | そして、ここで秘訣がある。米田の補題 18 | $$[\cat{C}, \Set](\cat{C}(a, -), F) \cong F a$$ 19 | を使い、さらに総称的な$F$をhom関手$\cat{C}(b, -)$ で置き換える。すると、次が得られる。 20 | $$[\cat{C}, \Set](\cat{C}(a, -), \cat{C}(b, -)) \cong \cat{C}(b, a)$$ 21 | 22 | `\begin{figure}[H] \centering`{=latex} 23 | ![](images/yoneda-embedding.jpg){width=60%} 24 | `\end{figure}`{=latex} 25 | 26 | \noindent 27 | これはまさに探していた2つのhom関手の間の自然変換だが、少しねじれがある。つまり、自然変換と射との対応は見つけたのだが、射――$\cat{C}(b, a)$ の要素――の向きが「間違って」いる。でも大丈夫だ。それは単に注目している関手が反変であることを意味する。 28 | 29 | `\begin{figure}[H] \centering`{=latex} 30 | ![](images/yoneda-embedding-2.jpg){width=65%} 31 | `\end{figure}`{=latex} 32 | 33 | \noindent 34 | 実際には、期待以上のものが得られた。$\cat{C}$から$[\cat{C}, \Set]$への写像は反変関手というだけではない――それは*充満忠実* (fully faithful) 関手なのだ。充満性と忠実性という特性は、関手がhom集合をどう写すかを述べている。 35 | 36 | *忠実* (faithful) 関手はhom集合上の*単射*だ。つまり、別々の射は別々の射へと写す。言い換えれば、射を潰さない。 37 | 38 | *充満* (full) 関手はhom集合上の*全射*だ。つまり、一方のhom集合をもう一方のhom集合の*上へ*写し、後者を完全にカバーする。 39 | 40 | 充満忠実関手$F$はhom集合上の[*全単射*]{.keyword #bijection}\index{全単射} (bijection) であり、つまり両方の集合のすべての要素が1対1で対応する。もとの圏$\cat{C}$内の対象$a$と$b$のすべてのペアに対して、$\cat{C}(a, b)$ と$\cat{D}(F a, F b)$ の間に全単射がある。ここで、$\cat{D}$は$F$の行き先の圏(この場合は関手圏$[\cat{C}, \Set]$)だ。ただし、これは$F$が*対象*について全単射であることを意味しないので注意してほしい。$\cat{D}$内の対象のうち$F$の像内にないものが存在する可能性があり、それらの対象についてのhom集合たちに関しては何も言えない。 41 | 42 | ## 埋め込み 43 | 44 | 先ほど説明した(反変)関手、すなわち、$\cat{C}$内の対象を$[\cat{C}, \Set]$内の関手に写す関手 45 | $$a \to \cat{C}(a, -)$$ 46 | は[*米田埋め込み*]{.keyword #Yoneda_embedding}\index{米田埋め込み} (Yoneda embedding) を定義する。それは圏$\cat{C}$(厳密に言うと反変なので圏$\cat{C}^\mathit{op}$)を関手圏$[\cat{C}, \Set]$の内部に*埋め込む*。$\cat{C}$内の対象を関手に写すだけでなく、それらの間のすべての接続を忠実に保持する。 47 | 48 | これは非常に有用な結果だ。なぜなら、数学者は関手圏について、特に余域が$\Set$である関手について多くのことを知っているからだ。任意の圏$\cat{C}$について、関手圏へ埋め込むことで多くの知見が得られる。 49 | 50 | もちろん米田埋め込みにも双対があり、それは余米田埋め込み (co-Yoneda embedding) と呼ばれることもある。議論の始めの時点で(始点となる対象ではなく)終点となる対象を固定したhom集合$\cat{C}(-, a)$ を考えても良かったことに着目しよう。そうすれば反変hom関手が得られていたことになる。$\cat{C}$から$\Set$への反変関手は、おなじみの前層だ (たとえば、第12章の[極限と余極限](#limits-and-colimits)を参照)。余米田埋め込みは圏$\cat{C}$の前層圏への埋め込みを定義する。射に対する作用は次によって与えられる。 51 | $$[\cat{C}^\mathit{op}, \Set](\cat{C}(-, a), \cat{C}(-, b)) \cong \cat{C}(a, b)$$ 52 | ここでも、数学者は前層圏について多くのことを知っているので、任意の圏をそれに埋め込めるのは大きな戦果だ。 53 | 54 | ## Haskellへの応用 55 | 56 | Haskellでの米田埋め込みは、式の一辺がreader関手同士の自然変換、他辺が(逆方向へ向かう)関数であるような同型として表せる。 57 | 58 | ```haskell 59 | forall x. (a -> x) -> (b -> x) ≅ b -> a 60 | ``` 61 | 62 | \noindent 63 | (Reader関手が`((->) a)`と等価であることを思い出してほしい。) 64 | 65 | この等式の左辺は、`a`から`x`への関数と型`b`の値が与えられたときに、型`x`の値を生成できるような多相関数である(ここでは非カリー化した視点で、つまり関数`b -> x`の周りの括弧を除いて考えている)。これをすべての`x`に対して行えるのは、関数が`b`を`a`に変換する方法を知っている場合だけだ。関数`b -> a`に密かにアクセスできる必要がある。 66 | 67 | そのようなコンバーター`btoa`があれば、この左辺を、`fromY`と呼ぶとして、以下のように定義できる。 68 | 69 | ```haskell 70 | fromY :: (a -> x) -> b -> x 71 | fromY f b = f (btoa b) 72 | ``` 73 | 74 | \noindent 75 | 逆に、関数`fromY`があれば、恒等射について`fromY`を呼び出すことでそのコンバーターを復元できる。 76 | 77 | ```haskell 78 | fromY id :: b -> a 79 | ``` 80 | 81 | \noindent 82 | これによって関数`fromY`と`btoa`の間に全単射が確立される。 83 | 84 | この同型を別の観点で見ると、`b`から`a`への関数を継続渡し形式で表しているとも見なせる。引数`a -> x`は継続(ハンドラー)であると見なせる^[訳注:この見方をするときは左辺の引数の順を入れ替えて`b -> (a -> x) -> x`とすることが多い。]。結果は`b`から`x`への関数であり、型`b`の値を引数として呼ばれたとき、エンコードされようとしている関数に前合成された継続を実行する。 85 | 86 | 米田埋め込みでHaskellのデータ構造のうちいくつかの別の表現についても説明できる。特に、レンズ[^lens-abstruct]の[非常に便利な表現](https://bartoszmilewski.com/2015/07/13/from-lenses-to-yoneda-embedding/)[^vanLaarhoven]を`Control.Lens`ライブラリーで提供する。 87 | 88 | [^lens-abstruct]: 訳注:ゲッターとセッターをペアにし合成可能にしたもの。第3部でも少し触れる。レンズについて初めて述べた下記の論文は後に2015年のMost Influential POPL Paper Awardを受賞している。 89 | 90 | * Nate Foster, Michael B. Greenwald, Jonathan T. Moore, Benjamin C. Pierce, Alan Schmitt. *Combinators for bi-directional tree transformations: a linguistic approach to the view update problem*. POPL 2005. pp. 233–246. 91 | 92 | また、以下の文献も参考になる。 93 | 94 | * 加藤 弘之, 胡 振江, 日高 宗一郎, 松田 一孝「『ソフトウェアサイエンスの基本』シリーズ第4回 高談闊論:双方向変換の原理と実践」『コンピュータ ソフトウェア』2014年, 31巻2号, pp. 44-56, 95 | * 日高 宗一郎「双方向変換 : 古典的なビュー更新問題から,プログラミング言語によるアプローチとソフトウェア開発への応用まで」『情報処理』2017年, 58巻12号, pp. 1114-1122, 96 | 97 | [^vanLaarhoven]: 98 | 99 | 訳注:van Laarhoven表現として知られる()。 100 | 101 | ## 前順序での例 102 | 103 | この節の例はRobert Harperによって提案された。前順序によって定義された圏に米田埋め込みを適用するものだ。前順序は要素間に順序関係がある集合であり、この順序関係は伝統的に$\leqslant$(小なりイコール)で記述される。前順序に「前」が付いているのは、関係が推移律 (transitive law) と反射律 (reflexive law) を満たす必要があるだけで、必ずしも反対称律 (antisymmetric law) を満たす必要はないからだ(すなわち、循環してもよい)[^order]。 104 | 105 | [^order]: 訳注:集合の任意の元$a, b, c$について 106 | 107 | * 推移律:$a \leqslant b$かつ$b \leqslant c$ならば$a \leqslant c$ 108 | * 反射律:$a \leqslant a$ 109 | * 反対称律:$a \leqslant b$かつ$b \leqslant a$ならば$a = b$ 110 | 111 | 前順序関係を持つ集合は圏をなす。対象となるのはその集合の各要素だ。対象$a$から$b$への射は、対象が比較できない場合や$a \leqslant b$が真でない場合には存在せず、$a \leqslant b$の場合には$a$から$b$への向きに存在する。ある対象から別の対象への射が2本以上存在することはない。したがって、このような圏のhom集合はすべて、空集合または単元集合だ。このような圏は*細い圏*と呼ばれる。 112 | 113 | この構成が実際に圏であることは簡単に納得できる。まず、射は合成可能だ。なぜなら、$a \leqslant b$かつ$b \leqslant c$ならば$a \leqslant c$だからだ。そして、合成は結合性を持つ。恒等射も存在する。なぜなら、すべての要素がそれ自身(以下)となる(もとになっている順序の反射律)からだ。 114 | 115 | これで前順序圏に余米田埋め込みを適用できるようになった。特に興味があるのは射に対する作用だ。 116 | $$[\cat{C}, \Set](\cat{C}(-, a), \cat{C}(-, b)) \cong \cat{C}(a, b)$$ 117 | 右辺のhom集合が空集合でないのは$a \leqslant b$のときだけだ。その場合は単元集合となる。したがって、$a \leqslant b$の場合、左辺には自然変換が1つだけ存在する。それ以外の場合は自然変換はない。 118 | 119 | では、前順序のhom関手間の自然変換とは何だろうか? それは2つの集合$\cat{C}(-, a)$ と$\cat{C}(-, b)$ の間の関数の族でなければならない。前順序集合では、2つの集合はそれぞれ空集合か単元集合だ。どんな関数があり得るか見てみよう。 120 | 121 | 空集合からそれ自身への関数(空集合に作用する恒等射)、空集合から単元集合への`absurd`関数(関数の値を定義すべき要素が空集合には1つもないので、何もしない)、そして単元集合からそれ自身への関数 (要素が1つの集合に作用する恒等射)がある。単元集合から空集合への組み合わせだけは禁じられている(そのような関数が単元集合の要素に作用したとして、どんな値を返せばよいだろう?)。 122 | 123 | つまり、この自然変換は決してhom単元集合をhom空集合に接続しない。言い換えると、$x \leqslant a$ (hom単元集合$\cat{C}(x, a)$) ならば$\cat{C}(x, b)$ は空集合ではない。空でない$\cat{C}(x, b)$ は$x$が$b$以下であることを意味する。したがって、ここでの自然変換が存在するためには、すべての$x$について、$x \leqslant a$ならば$x \leqslant b$が成り立つ必要がある。 124 | $$\text{任意の } x \text{ について } x \leqslant a \Rightarrow x \leqslant b$$ 125 | 一方、余米田の補題によると、この自然変換の存在は$\cat{C}(a, b)$ が空でないこと、つまり$a \leqslant b$であることと等価だ。まとめると、次の結果が得られる。 126 | $$a \leqslant b \text{ ならばそのときに限り任意の } x \text{ について } x \leqslant a \Rightarrow x \leqslant b$$ 127 | この結果に直接到達することもできただろう。直観的には、$a \leqslant b$ならば$a$以下のすべての要素も$b$以下である必要がある。逆に、$a$を右辺の$x$に代入すると、$a \leqslant b$となる。しかし、米田埋め込みを通じてこの結果に到達する方がはるかに刺激的なのは認めなければならない。 128 | 129 | ## 自然性 130 | 131 | 米田の補題は自然変換の集合と$\Set$の対象との間に同型射を設ける。いま扱っている自然変換たちは関手圏$[\cat{C}, \Set]$内の射だ。任意の2つの関手間の自然変換の集合は、関手圏におけるhom集合となる。米田の補題とは次の同型だ。 132 | $$[\cat{C}, \Set](\cat{C}(a, -), F) \cong F a$$ 133 | この同型は実は$F$についても$a$についても自然である。言い換えれば、積圏$[\cat{C}, \Set] \times \cat{C}$から取られたペア $(F, a)$ について自然だ。ここでは$F$を関手圏の*対象*として扱っていることに注意してほしい。 134 | 135 | これが何を意味するのか少し考えてみよう。自然同型は2つの関手の間の可逆な*自然変換*だ。そして実際、前述の同型の右辺は関手だ。具体的には$[\cat{C}, \Set]\times \cat{C}$から$\Set$への関手だ。ペア $(F, a)$ に対するその作用は集合――関手$F$を対象$a$において評価した結果――となる。この関手は評価関手 (evaluation functor) と呼ばれる。 136 | 137 | 左辺も関手であり、$(F, a)$ を自然変換の集合$[\cat{C}, \Set](\cat{C}(a, -), F)$ に変換する。 138 | 139 | これらが本当に関手だと示すには、射に対する作用も定義しなければならない。しかし、ペア $(F, a)$ と $(G, b)$ の間の射とは何だろうか? それは射のペア $(\Phi, f)$ だ。1番目は関手間の射――自然変換――であり、2番目は$\cat{C}$内の通常の射だ。 140 | 141 | 評価関手はこのペア $(\Phi, f)$ を取り、2つの集合$F a$と$G b$の間の関数に写す。このような関数は、$a$における$\Phi$の成分($F a$を$G a$に写す)と$G$によって持ち上げられた射$f$から、簡単に構築できる。 142 | $$(G f) \cdot \Phi_a$$ 143 | $\Phi$の自然性により、これは次と同じであることに注意してほしい。 144 | $$\Phi_b \cdot (F f)$$ 145 | この同型全体の自然性を証明するつもりはない――関手とは何かが掴めれば、ごく機械的に証明できる。それはこの同型が関手と自然変換から成り立っているという事実から導かれる。うまくいかないはずがない。 146 | 147 | ## 課題 148 | 149 | 1. 余米田埋め込みをHaskellで表現せよ。 150 | 1. `fromY`と`btoa`の間に確立された全単射が同型である(2つの写像が互いに逆である)ことを示せ。 151 | 1. 与えられたモノイドに対し、米田埋め込みを行え。そのモノイドの単一の対象に対応する関手は何か[^q16.5.3]? そのモノイドの射たちに対応する自然変換たちはどのようなものか? 152 | 1. *共変*米田埋め込みを前順序に適用したものは何か?(この問いはGershom Bazermanによって提案された。) 153 | 1. 米田埋め込みを使えば、任意の関手圏$[\cat{C}, \cat{D}]$を関手圏$[[\cat{C}, \cat{D}], \Set]$に埋め込める。それが射(この場合は自然変換)にどう作用するか説明せよ。 154 | 155 | [^q16.5.3]: 訳注:この問いは15章で出てきたケイリーの定理(のモノイド版)に関連する。また、モノイドが単一対象の圏として表せることについては[圏としてのモノイド](#monoid-as-set)(第3章4節)を参照。] 156 | -------------------------------------------------------------------------------- /japanese/index_html.md: -------------------------------------------------------------------------------- 1 | # 索引 {-} 2 | 3 | 4 | * [[1対1](#one-to-one){epub:type="index-locator"}]{epub:type="index-term"} 5 | * [[factorizer](#factorizer){epub:type="index-locator"}]{epub:type="index-term"} 6 | * [[hom集合](#hom-set){epub:type="index-locator"}]{epub:type="index-term"} 7 | * [[modus ponens](#modus_ponen){epub:type="index-locator"}]{epub:type="index-term"} 8 | * [[theorems for free](#theorems_for_free){epub:type="index-locator"}]{epub:type="index-term"} 9 | * [[variant](#variant){epub:type="index-locator"}]{epub:type="index-term"} 10 | * [[writerモナド](#writer_monad){epub:type="index-locator"}]{epub:type="index-term"} 11 | 12 | 13 | * [[アドホック多相](#ad_hoc_polymorphism){epub:type="index-locator"}]{epub:type="index-term"} 14 | * [[アリティ](#arity){epub:type="index-locator"}]{epub:type="index-term"} 15 | * [[一方向の](#one_way2){epub:type="index-locator"}]{epub:type="index-term"} 16 | * 意味論 17 | * [[操作的-](#operational_semantics){epub:type="index-locator"}]{epub:type="index-term"} 18 | * [[表示的-](#denotational_semantics){epub:type="index-locator"}]{epub:type="index-term"} 19 | * [[インスタンス](#instance){epub:type="index-locator"}]{epub:type="index-term"} 20 | * [[上への](#onto){epub:type="index-locator"}]{epub:type="index-term"} 21 | * [[埋め込み](#embedding){epub:type="index-locator"}]{epub:type="index-term"} 22 | 23 | 24 | * [[外延的](#extensional){epub:type="index-locator"}]{epub:type="index-term"} 25 | * [[型推論](#type_inference){epub:type="index-locator"}]{epub:type="index-term"} 26 | * [[カリー化](#currying){epub:type="index-locator"}]{epub:type="index-term"} 27 | * [[環](#ring){epub:type="index-locator"}]{epub:type="index-term"} 28 | * [[関数合成](#function_composition){epub:type="index-locator"}]{epub:type="index-term"} 29 | * [[関数適用](#function_application){epub:type="index-locator"}]{epub:type="index-term"} 30 | * [[基本的な積操作](#basic_product_operations){epub:type="index-locator"}]{epub:type="index-term"} 31 | * [[くさび条件](#wedge_condition){epub:type="index-locator"}]{epub:type="index-term"} 32 | * [[恒等射](#identity){epub:type="index-locator"}]{epub:type="index-term"} 33 | * [[合成可能](#composable){epub:type="index-locator"}]{epub:type="index-term"} 34 | * [[骨格](#skeleton){epub:type="index-locator"}]{epub:type="index-term"} 35 | 36 | 37 | * [[自己関手](#endofunctors){epub:type="index-locator"}]{epub:type="index-term"} 38 | * [[自然](#natural){epub:type="index-locator"}]{epub:type="index-term"} 39 | * [[自然性条件](#naturality_condition){epub:type="index-locator"}]{epub:type="index-term"} 40 | * 自然同型 -- [[a](#natural_isomorphism){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#naturally_isomorphic){epub:type="index-locator"}]{epub:type="index-term"} 41 | * [[始代数](#initial_algebra){epub:type="index-locator"}]{epub:type="index-term"} 42 | * [[射](#morphism){epub:type="index-locator"}]{epub:type="index-term"} 43 | * 自由 44 | * [[-関手](#free_functor){epub:type="index-locator"}]{epub:type="index-term"} 45 | * [[-圏](#free_category){epub:type="index-locator"}]{epub:type="index-term"} 46 | * [[-モノイド](#free_monoid){epub:type="index-locator"}]{epub:type="index-term"} 47 | * 述語 -- [[a](#predicate){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#predicate2){epub:type="index-locator"}]{epub:type="index-term"} 48 | * [[純粋関数](#pure_function){epub:type="index-locator"}]{epub:type="index-term"} 49 | * 準同型 -- [[a](#homomorphisms){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#homomorphism){epub:type="index-locator"}]{epub:type="index-term"} 50 | * [[証明を区別する関係](#proof-relevant_relation){epub:type="index-locator"}]{epub:type="index-term"} 51 | * [[シングルソート](#single-sorted){epub:type="index-locator"}]{epub:type="index-term"} 52 | * [[水平合成](#horizontal_composition){epub:type="index-locator"}]{epub:type="index-term"} 53 | * 随伴 54 | * [[左-](#left_adjoint){epub:type="index-locator"}]{epub:type="index-term"} 55 | * [[右-](#right_adjoint){epub:type="index-locator"}]{epub:type="index-term"} 56 | * [[成分](#component){epub:type="index-locator"}]{epub:type="index-term"} 57 | * [[線形順序](#linear_order){epub:type="index-locator"}]{epub:type="index-term"} 58 | * [[全射](#surjective){epub:type="index-locator"}]{epub:type="index-term"} 59 | * [[前順序](#preorder){epub:type="index-locator"}]{epub:type="index-term"} 60 | * [[全順序](#total_order){epub:type="index-locator"}]{epub:type="index-term"} 61 | * [[双デカルト閉](#bicartesian_closed){epub:type="index-locator"}]{epub:type="index-term"} 62 | * [[双関手](#bifunctor){epub:type="index-locator"}]{epub:type="index-term"} 63 | * 全単射 -- [[a](#bijections){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#bijection){epub:type="index-locator"}]{epub:type="index-term"} 64 | * [[双閉](#biclosed){epub:type="index-locator"}]{epub:type="index-term"} 65 | 66 | 67 | * 台集合 -- [[a](#underlying){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#underlying_set){epub:type="index-locator"}]{epub:type="index-term"} 68 | * [[対象](#object){epub:type="index-locator"}]{epub:type="index-term"} 69 | * [[対称](#symmetric){epub:type="index-locator"}]{epub:type="index-term"} 70 | * [[単射](#injective){epub:type="index-locator"}]{epub:type="index-term"} 71 | * [[チェイン](#chain){epub:type="index-locator"}]{epub:type="index-term"} 72 | * [[デカルト閉](#Cartesian_closed){epub:type="index-locator"}]{epub:type="index-term"} 73 | * [[デカルト積](#Cartesian_product){epub:type="index-locator"}]{epub:type="index-term"} 74 | * [[点](#point){epub:type="index-locator"}]{epub:type="index-term"} 75 | * [[テンプレートテンプレート仮引数](#template_template_parameter){epub:type="index-locator"}]{epub:type="index-term"} 76 | * [[テンソル積](#tensor_product){epub:type="index-locator"}]{epub:type="index-term"} 77 | * [[同型](#isomorphic){epub:type="index-locator"}]{epub:type="index-term"} 78 | * [[-射](#isomorphism){epub:type="index-locator"}]{epub:type="index-term"} 79 | * [[-を除いて](#up_to_isomorphism){epub:type="index-locator"}]{epub:type="index-term"} 80 | * [[等式による推論](#equational_reasoning){epub:type="index-locator"}]{epub:type="index-term"} 81 | * [[同値性](#equivalence){epub:type="index-locator"}]{epub:type="index-term"} 82 | * [[同値関係](#equivalence_relation){epub:type="index-locator"}]{epub:type="index-term"} 83 | * [[トポス](#topos){epub:type="index-locator"}]{epub:type="index-term"} 84 | 85 | 86 | * [[内部](#internal){epub:type="index-locator"}]{epub:type="index-term"} 87 | 88 | 89 | * [[パラメトリック多相](#parametric_polymorphism){epub:type="index-locator"}]{epub:type="index-term"} 90 | * [[半環](#semiring){epub:type="index-locator"}]{epub:type="index-term"} 91 | * [[半順序](#partial_order){epub:type="index-locator"}]{epub:type="index-term"} 92 | * [[-集合](#poset){epub:type="index-locator"}]{epub:type="index-term"} 93 | * [[反対圏](#opposite_category){epub:type="index-locator"}]{epub:type="index-term"} 94 | * [[反変](#contravariant){epub:type="index-locator"}]{epub:type="index-term"} 95 | * [[等しさ](#equality){epub:type="index-locator"}]{epub:type="index-term"} 96 | * [[評価](#evaluation){epub:type="index-locator"}]{epub:type="index-term"} 97 | * [[表現](#representation){epub:type="index-locator"}]{epub:type="index-term"} 98 | * 表現可能 -- [[a](#representable){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#representable2){epub:type="index-locator"}]{epub:type="index-term"} 99 | * [[-前層](#representable_presheaf){epub:type="index-locator"}]{epub:type="index-term"} 100 | * [[副作用](#side_effect){epub:type="index-locator"}]{epub:type="index-term"} 101 | * [[不動点](#fixed_point){epub:type="index-locator"}]{epub:type="index-term"} 102 | * [[普遍的構成](#universal_construction){epub:type="index-locator"}]{epub:type="index-term"} 103 | * [[プロ関手](#profunctor){epub:type="index-locator"}]{epub:type="index-term"} 104 | * [[文脈付き計算](#contextual_computation){epub:type="index-locator"}]{epub:type="index-term"} 105 | * [[冪](#exponential){epub:type="index-locator"}]{epub:type="index-term"} 106 | * [[ポイントフリー](#point-free){epub:type="index-locator"}]{epub:type="index-term"} 107 | * 忘却関手 -- [[a](#forgetful_functor){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#forgetful_functor2){epub:type="index-locator"}]{epub:type="index-term"} 108 | * 豊穣 -- [[a](#enriched){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#enriched2){epub:type="index-locator"}]{epub:type="index-term"} 109 | * [[-関手](#enriched_functor){epub:type="index-locator"}]{epub:type="index-term"} 110 | * [[ボトム](#bottom){epub:type="index-locator"}]{epub:type="index-term"} 111 | 112 | 113 | * [[持ち上げられた](#lifted){epub:type="index-locator"}]{epub:type="index-term"} 114 | * [[モナド](#monad){epub:type="index-locator"}]{epub:type="index-term"} 115 | * [[モノイダル圏](#monoidal_category){epub:type="index-locator"}]{epub:type="index-term"} 116 | 117 | 118 | * [[矢](#arrow){epub:type="index-locator"}]{epub:type="index-term"} 119 | * [[余等化子](#coequalizer){epub:type="index-locator"}]{epub:type="index-term"} 120 | * [[米田埋め込み](#Yoneda_embedding){epub:type="index-locator"}]{epub:type="index-term"} 121 | 122 | 123 | * [[リグ](#rig){epub:type="index-locator"}]{epub:type="index-term"} 124 | * [[レコード](#record){epub:type="index-locator"}]{epub:type="index-term"} 125 | * [[ローヴェア理論](#lawvere_theory){epub:type="index-locator"}]{epub:type="index-term"} 126 | 127 | 128 | -------------------------------------------------------------------------------- /japanese/part2/ch04.md: -------------------------------------------------------------------------------- 1 | # 表現可能関手 {#representable-functors} 2 | 3 | そろそろ集合について少し話すべき時が来た。数学者たちは集合論に対して愛憎する関係にある。集合論は数学にとってのアセンブリー言語だ――少なくともかつてはそうだった。圏論はある程度、集合論から距離を置こうとする。たとえば、すべての集合の集合は存在しないが、すべての集合の圏$\Set$なら存在する、というのはよく知られた事実だ。これは良い。一方で我々は、圏内の任意の2対象間の射たちは集合をなす、と仮定した。そしてそれをhom集合と名付けさえした。公平のために言うと、圏論には射たちが集合をなさないことがあるような分野もある^[訳注:ここでは2対象間の射たちについて述べている。$\Set$でも、すべての射の集まり自体は集合にならない。]。その代わりにそれらは別の圏の対象となる。hom集合の代わりにhom対象を使う圏は[*豊穣*]{.keyword #enriched}\index{豊穣}圏 (enriched category) と呼ばれる。だが、以下では古き良きhom集合を持つ圏に留まることにする。 4 | 5 | 集合は、圏論における対象たちから取り出せる特徴のない塊、というのが最も近い。集合は要素を含むが、それらについて多くは語れない。有限集合なら要素数を数えられる。基数 (cardinal number) を使えば、無限集合の要素数をある意味で数えられる。たとえば、自然数の集合も実数の集合も無限集合だが、前者は後者よりも小さい。しかし、驚くかもしれないが、有理数の集合は自然数の集合と同じ大きさだ。 6 | 7 | それ以外には、集合に関するすべての情報は、集合間の関数――特に、同型と呼ばれる可逆関数――として表せる。どこからどう見ても同型集合は同一だ。数学基礎論の研究者の逆鱗に触れる前に、等しさと同型には根本的に重要な区別があることを説明しておこう。これは数学の最新分野であるホモトピー型理論 (Homotopy Type Theory, HoTT) の主要な関心事の1つだ。ここでHoTTについて触れる理由は、それが計算からインスピレーションを得た純粋な数学理論で、主唱者の1人であるVladimir Voevodskyによる大きな発見が定理証明器Coqを研究しているときに得られたものだからだ。数学とプログラミングの相互作用は双方向なのだ。 8 | 9 | 集合に関する重要な教訓は、別種の要素からなる集合同士を比較しても問題ないということだ。たとえば、任意の自然変換の集合は何らかの射の集合と同型である、などと主張できる。集合は集合にすぎないからだ。この場合の同型は単に、一方の集合に属するどの自然変換に対しても他方の集合に属する一意な射が存在し、その逆もまた成り立つことを意味する。それらは互いにペアにできる。リンゴとオレンジが異なる圏の対象なら比較できないが、リンゴの集合とオレンジの集合は比較できる。多くの場合、圏論の問題を集合論の問題に変換すれば、必要な洞察が得られ、有用な定理を証明することさえ可能になる。 10 | 11 | ## Hom関手 12 | 13 | すべての圏には、$\Set$への写像のカノニカルな族が用意されている。それらの写像は実際には関手であるため、圏の構造を保存している。そのような写像を1つ構築しよう。 14 | 15 | $\cat{C}$内のある対象$a$を固定し、同じく$\cat{C}$内の別の対象$x$を選択しよう。Hom集合$\cat{C}(a, x)$ は集合であり、$\Set$の対象だ。$a$を固定したまま$x$を変化させると、$\cat{C}(a, x)$ も$\Set$内で変化する。それゆえ、$x$から$\Set$への写像が得られる。 16 | 17 | `\begin{figure}[H] \centering`{=latex} 18 | ![](images/hom-set.jpg){width=45%} 19 | `\end{figure}`{=latex} 20 | 21 | \noindent 22 | hom集合を2番目の引数に関する写像と見なしていることを強調したい場合は$\cat{C}(a, -)$ と表記する。ここで、ダッシュは引数のプレースホルダーを表している。 23 | 24 | この対象の写像は射の写像へと容易に拡張できる。$\cat{C}$内の任意の2対象$x$と$y$の間の射$f$を考えてみよう。先ほど定義した写像によって、対象$x$は集合$\cat{C}(a, x)$ に写され、対象$y$は$\cat{C}(a, y)$ に写される。この写像が関手となるなら、$f$は2つの集合間の関数$\cat{C}(a, x) \to \cat{C}(a, y)$ に写されなければならない。 25 | 26 | この関数を点ごとに、つまり、引数ごとに個別に定義しよう。引数として$\cat{C}(a, x)$ の任意の要素を1つ選択する必要がある。それを$h$と呼ぶことにする。射たちは端と端が一致すれば合成できる。たまたま$h$の終点が$f$の始点と一致しているので、それらの合成 27 | $$f \circ h \Colon a \to y$$ 28 | は$a$から$y$への射となる。したがって、これは$\cat{C}(a, y)$ の元だ。 29 | 30 | `\begin{figure}[H] \centering`{=latex} 31 | ![Hom関手](images/hom-functor.jpg){width=45%} 32 | `\end{figure}`{=latex} 33 | 34 | \noindent 35 | 先ほど、$\cat{C}(a, x)$ から$\cat{C}(a, y)$ への関数を見つけた。これは$f$の像として使える。混乱のおそれがない場合は、この持ち上げられた関数を$\cat{C}(a, f)$と記し、射$h$に対する作用を次のように記すことにしよう。 36 | $$\cat{C}(a, f) h = f \circ h$$ 37 | この構成はどの圏でも機能するので、Haskellの型の圏でも機能するはずだ。Haskellでは、hom関手は`Reader`関手としてよく知られている。 38 | 39 | ```haskell 40 | type Reader a x = a -> x 41 | ``` 42 | 43 | ```haskell 44 | instance Functor (Reader a) where 45 | fmap f h = f . h 46 | ``` 47 | 48 | \noindent 49 | さて、Hom集合の始点を固定する代わりに終点を固定すると何が起こるかを考えてみよう。言い換えれば、写像$\cat{C}(-, a)$ も関手なのかを問うている。答えはそのとおり、関手なのだが、共変関手ではなく反変関手になる。射の端と端を同様にマッチングすると$f$との後合成となり、$\cat{C}(a, -)$ の場合のような前合成ではないからだ。 50 | 51 | この反変関手はHaskellですでに見た。それは`Op`と呼ばれていた。 52 | 53 | ```haskell 54 | type Op a x = x -> a 55 | ``` 56 | 57 | ```haskell 58 | instance Contravariant (Op a) where 59 | contramap f h = h . f 60 | ``` 61 | 62 | \noindent 63 | 最後に、両方の対象を変化させると、プロ関手$\cat{C}(-, =)$ が得られる。これは1つ目の引数について反変で、2つ目の引数について共変だ(2つの引数が独立して変化することを強調するため、2つ目のプレースホルダーとしてダブルダッシュを使った)。このプロ関手については、関手性について述べたときにすでに見た。 64 | 65 | ```haskell 66 | instance Profunctor (->) where 67 | dimap ab cd bc = cd . bc . ab 68 | lmap = flip (.) 69 | rmap = (.) 70 | ``` 71 | 72 | \noindent 73 | 重要な教訓として、対象たちをhom集合へ写すことは関手的である、という観察はすべての圏に当てはまる。反変性は反対圏から写すことと等価なので、この事実は簡潔にこう記せる。 74 | $$C(-, =) \Colon \cat{C}^\mathit{op} \times \cat{C} \to \Set$$ 75 | 76 | ## 表現可能関手 77 | 78 | これまでに見たように、$\cat{C}$内の対象$a$の選択ごとに$\cat{C}$から$\Set$への関手が得られる。構造を保存する$\Set$へのこの種の写像は[*表現*]{.keyword #representation}\index{表現} (representation) とよく呼ばれる。つまり、$\cat{C}$における対象や射を$\Set$内の集合や関数として表現しているということだ。 79 | 80 | 関手$\cat{C}(a, -)$ 自体を指して表現可能関手と呼ぶこともある。より一般には、ある$a$の選択に対してhom関手と自然同型である関手$F$はすべて[*表現可能*]{.keyword #representable}\index{表現可能} (representable) 関手と呼ばれる。このような関手は必然的に集合値 ($\Set$-valued) 関手となる。$\cat{C}(a, -)$ がそうだからだ。 81 | 82 | 以前述べたように、同型集合は同一と見なされることが多い。より一般には、圏の同型*対象*は同一と見なされる。対象たちは他の対象たち(およびそれら自身)との射による関係だけしか構造を持たないからだ。 83 | 84 | たとえば、モノイドの圏$\cat{Mon}$について前に説明した。それは最初は集合たちでモデル化されていた。ただし、それらの集合によるモノイドの構造を保存する関数のみを射として選ぶように気を付けた。そのため、$\cat{Mon}$内の2つの対象は、同型なら、つまり可逆な射が間にあるなら、全く同じ構造を持つ。それらが基づく集合と関数を覗き見ると、一方のモノイドの単位元がもう一方のモノイドの単位元へと写され、2つの要素の積がそれらの要素を写したものの積へと写されているのが分かるだろう。 85 | 86 | 同じ推論が関手にも適用できる。2つの圏の間の関手は圏をなし、そこでは自然変換が射の役割を果たしている。したがって、2つの関手の間に可逆な自然変換があれば、それらは同型であり、同一と見なせる。 87 | 88 | この観点から表現可能関手の定義を分析してみよう。$F$が表現可能となるには次が必要だ。$\cat{C}$内に対象$a$があり、$\cat{C}(a, -)$から$F$への自然変換$\alpha$があり、逆方向に別の自然変換$\beta$があり、それらの合成が恒等自然変換である。 89 | 90 | ある対象$x$における$\alpha$の成分を見てみよう。それは$\Set$内の関数だ。 91 | $$\alpha_x \Colon \cat{C}(a, x) \to F x$$ 92 | この変換の自然性条件は、$x$から$y$への任意の射$f$について、次の関係を表す図式が可換となることを示している。 93 | $$F f \circ \alpha_x = \alpha_y \circ \cat{C}(a, f)$$ 94 | Haskellでは、自然変換を多相関数で置き換えることになる。 95 | 96 | ```haskell 97 | alpha :: forall x. (a -> x) -> F x 98 | ``` 99 | 100 | \noindent 101 | ここで使った量化子`forall`は必須ではない。自然性条件 102 | 103 | ```haskell 104 | fmap f . alpha = alpha . fmap f 105 | ``` 106 | 107 | \noindent 108 | はパラメトリシティ (parametricity) によって自動的に満たされる(この自然性条件は前述のtheorems for freeのひとつだ)。これは、左辺の`fmap`が関手$F$によって定義され、右辺の`fmap`がreader関手によって定義されるという理解に基づく。readerの`fmap`は単なる関数の前合成^[訳注:引数の関数`f`にreaderの関数を前合成する。]なので、さらにはっきりと書ける。$\cat{C}(a, x)$ の要素である$h$に作用したときの自然性条件は次のように簡潔に書ける。 109 | 110 | ```haskell 111 | fmap f (alpha h) = alpha (f . h) 112 | ``` 113 | 114 | \noindent 115 | もう1つの変換`beta`は方向が逆だ。 116 | 117 | ```haskell 118 | beta :: forall x. F x -> (a -> x) 119 | ``` 120 | 121 | \noindent 122 | この関数も自然性条件を満たす必要があり、そして`alpha`の逆関数でなければならない。 123 | 124 | ```haskell 125 | alpha . beta = id = beta . alpha 126 | ``` 127 | 128 | \noindent 129 | 後で説明するとおり、$F a$が空でないならば常に$\cat{C}(a, -)$ から任意の集合値関手への自然変換が存在する(米田の補題)が、この変換は可逆であるとは限らない。 130 | 131 | Haskellでリスト関手を用い、`Int`を`a`とした例を挙げよう。以下が具体的な自然変換の一例だ。 132 | 133 | ```haskell 134 | alpha :: forall x. (Int -> x) -> [x] 135 | alpha h = map h [12] 136 | ``` 137 | 138 | \noindent 139 | 勝手な数として12を選び、それを使って単要素リストを作成した。次に、このリストに関数`h`を`fmap`し、`h`の戻り値の型のリストを取得する。(実際には、そのような変換は整数のリストと同じくらいたくさんある。) 140 | 141 | 自然性条件は`map`(`fmap`のリスト版)の合成可能性と等価だ。 142 | 143 | ```haskell 144 | map f (map h [12]) = map (f . h) [12] 145 | ``` 146 | 147 | \noindent 148 | しかし、逆変換を見つけるには、任意の型`x`のリストをもとに`x`を返す関数を探さなくてはならない。 149 | 150 | ```haskell 151 | beta :: forall x. [x] -> (Int -> x) 152 | ``` 153 | 154 | \noindent 155 | `head`か何かを使ってリストから`x`を取得しようと考えたかもしれないが、空のリストには使えない。(`Int`の箇所の)型`a`の選択肢としてここで使えるものがないことに注目してほしい。すなわち、リスト関手は表現可能ではない。 156 | 157 | Haskellの(自己)関手がコンテナーに少し似ていると言ったのを覚えているだろうか? 同じように、表現可能関手は関数呼び出しの結果をメモ化して保存するためのコンテナーと見なせる(Haskellでのhom集合の要素は単なる関数だ)。表現対象 (representing object)、すなわち$\cat{C}(a, -)$ における型$a$はキー型と見なせて、それを用いれば表化 (tabulate) された関数値にアクセスできる。ここでの変換`alpha`は`tabulate`と呼ばれ、その逆の`beta`は`index`と呼ばれる。以下に(少し単純化した)`Representable`のクラス定義を示す。 158 | 159 | ```haskell 160 | class Representable f where 161 | type Rep f :: * 162 | tabulate :: (Rep f -> x) -> f x 163 | index :: f x -> Rep f -> x 164 | ``` 165 | 166 | \noindent 167 | 表現型、すなわち$a$が、ここでは`Rep f`と呼ばれ、`Representable`の定義の一部であることに注目してほしい。スターは`Rep f`が型である(型構成子や他のエキゾチックな種ではない)ことを意味する^[訳注:事実標準のHaskell処理系のGHCでは、現在はこの用法でのスター`*`は非推奨となっている。代わりに`Data.Kind`モジュールが提供する`Type`を用いる。]。 168 | 169 | 無限リストや無限ストリームは、空ではあり得ず、表現可能だ。 170 | 171 | ```haskell 172 | data Stream x = Cons x (Stream x) 173 | ``` 174 | 175 | \noindent 176 | それらは`Integer`を引数に取る関数の値をメモ化したものと見なせる。(厳密に言えば、非負整数を使うべきだが、コードを複雑にしたくなかった^[訳注:`Integer`の代わりに`Numeric.Natural`モジュールが提供する`Natural`を用いればよい。]。) 177 | 178 | このような関数を`tabulate`にするには、値の無限ストリームを作成する。もちろん、これが可能なのはHaskellが遅延評価だからだ。つまり、値は必要になったとき評価される。メモ化された値にアクセスするには`index`を使う。 179 | 180 | ```haskell 181 | instance Representable Stream where 182 | type Rep Stream = Integer 183 | tabulate f = Cons (f 0) (tabulate (f . (+1))) 184 | index (Cons b bs) n = 185 | if n == 0 then b else index bs (n - 1) 186 | ``` 187 | 188 | \noindent 189 | 任意の戻り値型を持つ関数の族をすべてカバーするような単一のメモ化スキームを実装できるのは興味深い。 190 | 191 | 反変関手の表現可能性も同様に定義される。ただし、$\cat{C}(-, a)$ の2番目の引数を固定する。あるいは、$\cat{C}^\mathit{op}$から$\Set$への関手を考えるのでも等価だ。$\cat{C}^\mathit{op}(a, -)$ は$\cat{C}(-, a)$ と同じだからだ。 192 | 193 | 表現可能性には興味深いひねりがある。デカルト閉圏では、hom集合を内部的には冪対象として扱えることを思い出してほしい。hom集合$\cat{C}(a, x)$ は$x^a$と等価で、表現可能関手$F$に対しては$-^a = F$と書ける。 194 | 195 | 試しに、両辺の対数を取ってみると$a = \mathbf{log}F$となる。 196 | 197 | もちろん、これは純粋に形式的な変換だが、対数の性質を多少知っているなら非常に便利だ。特に、直積型に基づく関手は直和型を用いて表現でき^[訳注:すなわち、上で言うところの$a$が直和型になるということ。]、直和型の関手は一般に表現可能ではないことが知られている(例:リスト関手)。 198 | 199 | 最後に、表現可能関手が同じものに対する2種類の実装――ひとつは関数、もうひとつはデータ構造――を与えることに注目してほしい。それらの内容は全く同じだ――同じキーを使えば同じ値が取得される。それが、語ろうとしていた「同一性」の感覚だ。2つの自然同型な関手は内容に関する限り同一だ。その一方で、2つの表現は異なる方法で実装されることが多く、パフォーマンス特性が異なり得る。メモ化はパフォーマンス改善策として使われ、実行時間の大幅な短縮につながり得る。同じ計算を背景とする異なる表現を生成できることは、実用上の価値が非常に高い。そのため、驚くべきことに、圏論はパフォーマンスを全く考慮しないにもかかわらず、実用上の価値を持つ別の実装を探求する十分な機会を与えてくれる。 200 | 201 | ## 課題 202 | 203 | 1. Hom関手が$\cat{C}$内の恒等射を$\Set$内の対応する恒等関数に写すことを示せ。 204 | 205 | 1. `Maybe`が表現可能でないことを示せ。 206 | 207 | 1. `Reader`関手は表現可能か? 208 | 209 | 1. `Stream`表現を使って、引数を2乗する関数をメモ化せよ。 210 | 211 | 1. `Stream`に対する`tabulate`と`index`が実際に互いに逆であることを示せ。(ヒント:数学的帰納法を使う。) 212 | 213 | 1. 次の関手 214 | 215 | ```haskell 216 | Pair a = Pair a a 217 | ``` 218 | 219 | \noindent 220 | は表現可能だ。それを表現する型が分かるだろうか? 221 | `tabulate`と`index`を実装せよ。 222 | 223 | ## 参考文献 224 | 225 | 1. [表現可能関手についてのCatstersの動画](https://www.youtube.com/watch?v=4QgjKUzyrhM)^[] 226 | -------------------------------------------------------------------------------- /english/index_html.md: -------------------------------------------------------------------------------- 1 | # Index {-} 2 | 3 | 4 | * [[ad hoc polymorphism](#ad_hoc_polymorphism){epub:type="index-locator"}]{epub:type="index-term"} 5 | * [[arity](#arity){epub:type="index-locator"}]{epub:type="index-term"} 6 | * [[arrows](#arrow){epub:type="index-locator"}]{epub:type="index-term"} 7 | 8 | 9 | * [[basic product operations](#basic_product_operations){epub:type="index-locator"}]{epub:type="index-term"} 10 | * [[bicartesian closed](#bicartesian_closed){epub:type="index-locator"}]{epub:type="index-term"} 11 | * [[biclosed](#biclosed){epub:type="index-locator"}]{epub:type="index-term"} 12 | * [[bifunctor](#bifunctor){epub:type="index-locator"}]{epub:type="index-term"} 13 | * bijection -- [[a](#bijections){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#bijection){epub:type="index-locator"}]{epub:type="index-term"} 14 | * [[bottom](#bottom){epub:type="index-locator"}]{epub:type="index-term"} 15 | 16 | 17 | * [[Cartesian closed](#Cartesian_closed){epub:type="index-locator"}]{epub:type="index-term"} 18 | * [[Cartesian product](#Cartesian_product){epub:type="index-locator"}]{epub:type="index-term"} 19 | * [[chains](#chain){epub:type="index-locator"}]{epub:type="index-term"} 20 | * [[coequalizer](#coequalizer){epub:type="index-locator"}]{epub:type="index-term"} 21 | * [[component](#component){epub:type="index-locator"}]{epub:type="index-term"} 22 | * [[composable](#composable){epub:type="index-locator"}]{epub:type="index-term"} 23 | * [[contextual computation](#contextual_computation){epub:type="index-locator"}]{epub:type="index-term"} 24 | * [[contravariant](#contravariant){epub:type="index-locator"}]{epub:type="index-term"} 25 | * [[currying](#currying){epub:type="index-locator"}]{epub:type="index-term"} 26 | 27 | 28 | * [[denotational semantics](#denotational_semantics){epub:type="index-locator"}]{epub:type="index-term"} 29 | 30 | 31 | * [[embedding](#embedding){epub:type="index-locator"}]{epub:type="index-term"} 32 | * [[endofunctors](#endofunctors){epub:type="index-locator"}]{epub:type="index-term"} 33 | * [[enriched](#enriched){epub:type="index-locator"}]{epub:type="index-term"} 34 | * [[enriched functor](#enriched_functor){epub:type="index-locator"}]{epub:type="index-term"} 35 | * [[equality](#equality){epub:type="index-locator"}]{epub:type="index-term"} 36 | * [[equational reasoning](#equational_reasoning){epub:type="index-locator"}]{epub:type="index-term"} 37 | * [[equivalence](#equivalence){epub:type="index-locator"}]{epub:type="index-term"} 38 | * [[equivalence relation](#equivalence_relation){epub:type="index-locator"}]{epub:type="index-term"} 39 | * [[evaluation](#evaluation){epub:type="index-locator"}]{epub:type="index-term"} 40 | * [[exponential](#exponential){epub:type="index-locator"}]{epub:type="index-term"} 41 | * [[extensional](#extensional){epub:type="index-locator"}]{epub:type="index-term"} 42 | 43 | 44 | * [[factorizer](#factorizer){epub:type="index-locator"}]{epub:type="index-term"} 45 | * [[fixed point](#fixed_point){epub:type="index-locator"}]{epub:type="index-term"} 46 | * forgetful functor -- [[a](#forgetful_functor){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#forgetful_functor2){epub:type="index-locator"}]{epub:type="index-term"} 47 | * [[free category](#free_category){epub:type="index-locator"}]{epub:type="index-term"} 48 | * [[free functor](#free_functor){epub:type="index-locator"}]{epub:type="index-term"} 49 | * [[free monoid](#free_monoid){epub:type="index-locator"}]{epub:type="index-term"} 50 | * [[function application](#function_application){epub:type="index-locator"}]{epub:type="index-term"} 51 | * [[function composition](#function_composition){epub:type="index-locator"}]{epub:type="index-term"} 52 | 53 | 54 | * [[hom-set](#hom-set){epub:type="index-locator"}]{epub:type="index-term"} 55 | * homomorphism -- [[a](#homomorphisms){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#homomorphism){epub:type="index-locator"}]{epub:type="index-term"} 56 | * [[horizontal composition](#horizontal_composition){epub:type="index-locator"}]{epub:type="index-term"} 57 | 58 | 59 | * [[identity](#identity){epub:type="index-locator"}]{epub:type="index-term"} 60 | * [[initial algebra](#initial_algebra){epub:type="index-locator"}]{epub:type="index-term"} 61 | * [[injective](#injective){epub:type="index-locator"}]{epub:type="index-term"} 62 | * [[instance](#instance){epub:type="index-locator"}]{epub:type="index-term"} 63 | * [[internal](#internal){epub:type="index-locator"}]{epub:type="index-term"} 64 | * [[isomorphic](#isomorphic){epub:type="index-locator"}]{epub:type="index-term"} 65 | * [[isomorphism](#isomorphism){epub:type="index-locator"}]{epub:type="index-term"} 66 | 67 | 68 | * [[Lawvere theory](#lawvere_theory){epub:type="index-locator"}]{epub:type="index-term"} 69 | * [[left adjoint](#left_adjoint){epub:type="index-locator"}]{epub:type="index-term"} 70 | * [[lifted](#lifted){epub:type="index-locator"}]{epub:type="index-term"} 71 | * [[linear order](#linear_order){epub:type="index-locator"}]{epub:type="index-term"} 72 | 73 | 74 | * [[modus ponens](#modus_ponen){epub:type="index-locator"}]{epub:type="index-term"} 75 | * [[monad](#monad){epub:type="index-locator"}]{epub:type="index-term"} 76 | * [[monoidal category](#monoidal_category){epub:type="index-locator"}]{epub:type="index-term"} 77 | * [[morphisms](#morphism){epub:type="index-locator"}]{epub:type="index-term"} 78 | 79 | 80 | * [[natural](#natural){epub:type="index-locator"}]{epub:type="index-term"} 81 | * [[natural isomorphism](#natural_isomorphism){epub:type="index-locator"}]{epub:type="index-term"} 82 | * [[naturality condition](#naturality_condition){epub:type="index-locator"}]{epub:type="index-term"} 83 | * [[naturally isomorphic](#naturally_isomorphic){epub:type="index-locator"}]{epub:type="index-term"} 84 | 85 | 86 | * [[object](#object){epub:type="index-locator"}]{epub:type="index-term"} 87 | * [[one-to-one](#one-to-one){epub:type="index-locator"}]{epub:type="index-term"} 88 | * one way - [[a](#one_way){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#one_way2){epub:type="index-locator"}]{epub:type="index-term"} 89 | * [[onto](#onto){epub:type="index-locator"}]{epub:type="index-term"} 90 | * [[operational semantics](#operational_semantics){epub:type="index-locator"}]{epub:type="index-term"} 91 | * [[opposite category](#opposite_category){epub:type="index-locator"}]{epub:type="index-term"} 92 | 93 | 94 | * [[parametric polymorphism](#parametric_polymorphism){epub:type="index-locator"}]{epub:type="index-term"} 95 | * [[partial order](#partial_order){epub:type="index-locator"}]{epub:type="index-term"} 96 | * [[point-free](#point-free){epub:type="index-locator"}]{epub:type="index-term"} 97 | * [[points](#point){epub:type="index-locator"}]{epub:type="index-term"} 98 | * [[poset](#poset){epub:type="index-locator"}]{epub:type="index-term"} 99 | * predicate -- [[a](#predicates){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#predicate){epub:type="index-locator"}]{epub:type="index-term"} 100 | * [[preorder](#preorder){epub:type="index-locator"}]{epub:type="index-term"} 101 | * [[profunctor](#profunctor){epub:type="index-locator"}]{epub:type="index-term"} 102 | * [[proof-relevant relation](#proof-relevant_relation){epub:type="index-locator"}]{epub:type="index-term"} 103 | * [[pure functions](#pure_function){epub:type="index-locator"}]{epub:type="index-term"} 104 | 105 | 106 | * [[record](#record){epub:type="index-locator"}]{epub:type="index-term"} 107 | * representable -- [[a](#representable){epub:type="index-locator"}]{epub:type="index-term"}, [[b](#representable2){epub:type="index-locator"}]{epub:type="index-term"} 108 | * [[representable presheaf](#representable_presheaf){epub:type="index-locator"}]{epub:type="index-term"} 109 | * [[representation](#representation){epub:type="index-locator"}]{epub:type="index-term"} 110 | * [[rig](#rig){epub:type="index-locator"}]{epub:type="index-term"} 111 | * [[right adjoint](#right_adjoint){epub:type="index-locator"}]{epub:type="index-term"} 112 | * [[ring](#ring){epub:type="index-locator"}]{epub:type="index-term"} 113 | 114 | 115 | * [[semiring](#semiring){epub:type="index-locator"}]{epub:type="index-term"} 116 | * [[side effects](#side_effect){epub:type="index-locator"}]{epub:type="index-term"} 117 | * [[single-sorted](#single-sorted){epub:type="index-locator"}]{epub:type="index-term"} 118 | * [[skeleton](#skeleton){epub:type="index-locator"}]{epub:type="index-term"} 119 | * [[surjective](#surjective){epub:type="index-locator"}]{epub:type="index-term"} 120 | * [[symmetric](#symmetric){epub:type="index-locator"}]{epub:type="index-term"} 121 | 122 | 123 | * [[template template parameter](#template_template_parameter){epub:type="index-locator"}]{epub:type="index-term"} 124 | * [[tensor product](#tensor_product){epub:type="index-locator"}]{epub:type="index-term"} 125 | * [[theorems for free](#theorems_for_free){epub:type="index-locator"}]{epub:type="index-term"} 126 | * [[topos](#topos){epub:type="index-locator"}]{epub:type="index-term"} 127 | * [[total](#total){epub:type="index-locator"}]{epub:type="index-term"} 128 | * [[total order](#total_order){epub:type="index-locator"}]{epub:type="index-term"} 129 | * [[type inference](#type_inference){epub:type="index-locator"}]{epub:type="index-term"} 130 | 131 | 132 | * [[underlying](#underlying){epub:type="index-locator"}]{epub:type="index-term"} 133 | * [[underlying set](#underlying_set){epub:type="index-locator"}]{epub:type="index-term"} 134 | * [[universal construction](#universal_construction){epub:type="index-locator"}]{epub:type="index-term"} 135 | * [[up to isomorphism](#up_to_isomorphism){epub:type="index-locator"}]{epub:type="index-term"} 136 | 137 | 138 | * [[variant](#variant){epub:type="index-locator"}]{epub:type="index-term"} 139 | 140 | 141 | * [[wedge condition](#wedge_condition){epub:type="index-locator"}]{epub:type="index-term"} 142 | * [[writer monad](#writer_monad){epub:type="index-locator"}]{epub:type="index-term"} 143 | 144 | 145 | * [[Yoneda embedding](#Yoneda_embedding){epub:type="index-locator"}]{epub:type="index-term"} 146 | -------------------------------------------------------------------------------- /english/part3/ch01.md: -------------------------------------------------------------------------------- 1 | \setcounter{part}{2} 2 | \setcounter{chapter}{16} 3 | \part{} 4 | 5 | # It's All About Morphisms 6 | 7 | If I haven't convinced you yet that category theory is all about morphisms then I haven't done my job properly. Since the next topic is adjunctions, which are defined in terms of isomorphisms of hom-sets, it makes sense to review our intuitions about the building blocks of hom-sets. Also, you'll see that adjunctions provide a more general language to describe a lot of constructions we've studied before, so it might help to review them too. 8 | 9 | ## Functors 10 | 11 | To begin with, you should really think of functors as mappings of morphisms --- the view that's emphasized in the Haskell definition of the `Functor` typeclass, which revolves around `fmap`. Of course, functors also map objects --- the endpoints of morphisms --- otherwise we wouldn't be able to talk about preserving composition. Objects tell us which pairs of morphisms are composable. The target of one morphism must be equal to the source of the other --- if they are to be composed. So if we want the composition of morphisms to be mapped to the composition of [*lifted*]{.keyword #lifted}\index{lifted} morphisms, the mapping of their endpoints is pretty much determined. 12 | 13 | ## Commuting Diagrams 14 | 15 | A lot of properties of morphisms are expressed in terms of commuting diagrams. If a particular morphism can be described as a composition of other morphisms in more than one way, then we have a commuting diagram. 16 | 17 | In particular, commuting diagrams form the basis of almost all universal constructions (with the notable exceptions of the initial and terminal objects). We've seen this in the definitions of products, coproducts, various other (co-)limits, exponential objects, free monoids, etc. 18 | 19 | The product is a simple example of a universal construction. We pick two objects $a$ and $b$ and see if there exists an object $c$, together with a pair of morphisms $p$ and $q$, that has the universal property of being their product. 20 | 21 | `\begin{figure}[H] \centering`{=latex} 22 | ![](images/productranking.jpg){width=30%} 23 | `\end{figure}`{=latex} 24 | \noindent 25 | A product is a special case of a limit. A limit is defined in terms of cones. A general cone is built from commuting diagrams. Commutativity of those diagrams may be replaced with a suitable naturality condition for the mapping of functors. This way commutativity is reduced to the role of the assembly language for the higher level language of natural transformations. 26 | 27 | ## Natural Transformations 28 | 29 | In general, natural transformations are very convenient whenever we need a mapping from morphisms to commuting squares. Two opposing sides of a naturality square are the mappings of some morphism $f$ under two functors $F$ and $G$. The other sides are the components of the natural transformation (which are also morphisms). 30 | 31 | `\begin{figure}[H] \centering`{=latex} 32 | ![](images/3_naturality.jpg){width=35%} 33 | `\end{figure}`{=latex} 34 | \noindent 35 | Naturality means that when you move to the "neighboring" component (by neighboring I mean connected by a morphism), you're not going against the structure of either the category or the functors. It doesn't matter whether you first use a component of the natural transformation to bridge the gap between objects, and then jump to its neighbor using the functor; or the other way around. The two directions are orthogonal. A natural transformation moves you left and right, and the functors move you up and down or back and forth --- so to speak. You can visualize the *image* of a functor as a sheet in the target category. A natural transformation maps one such sheet corresponding to $F$, to another, corresponding to $G$. 36 | 37 | `\begin{figure}[H] \centering`{=latex} 38 | ![](images/sheets.png){width=35%} 39 | `\end{figure}`{=latex} 40 | \noindent 41 | We've seen examples of this orthogonality in Haskell. There the action of a functor modifies the content of a container without changing its shape, while a natural transformation repackages the untouched contents into a different container. The order of these operations doesn't matter. 42 | 43 | We've seen the cones in the definition of a limit replaced by natural transformations. Naturality ensures that the sides of every cone commute. Still, a limit is defined in terms of mappings *between* cones. These mappings must also satisfy commutativity conditions. (For instance, the triangles in the definition of the product must commute.) 44 | 45 | These conditions, too, may be replaced by naturality. You may recall that the *universal* cone, or the limit, is defined as a natural transformation between the (contravariant) hom-functor: 46 | $$F \Colon c \to \cat{C}(c, \Lim{D})$$ 47 | and the (also contravariant) functor that maps objects in $\cat{C}$ to cones, which themselves are natural transformations: 48 | $$G \Colon c \to \Nat(\Delta_c, D)$$ 49 | Here, $\Delta_c$ is the constant functor, and $D$ is the functor that defines the diagram in $\cat{C}$. Both functors $F$ and $G$ have well defined actions on morphisms in $\cat{C}$. It so happens that this particular natural transformation between $F$ and $G$ is an *isomorphism*. 50 | 51 | ## Natural Isomorphisms 52 | 53 | A natural isomorphism --- which is a natural transformation whose every component is reversible --- is category theory's way of saying that "two things are the same." A component of such a transformation must be an isomorphism between objects --- a morphism that has the inverse. If you visualize functor images as sheets, a natural isomorphism is a one-to-one invertible mapping between those sheets. 54 | 55 | ## Hom-Sets 56 | 57 | But what are morphisms? They do have more structure than objects: unlike objects, morphisms have two ends. But if you fix the source and the target objects, the morphisms between the two form a boring set (at least for locally small categories). We can give elements of this set names like $f$ or $g$, to distinguish one from another --- but what is it, really, that makes them different? 58 | 59 | The essential difference between morphisms in a given hom-set lies in the way they compose with other morphisms (from abutting hom-sets). If there is a morphism $h$ whose composition (either pre- or post-) with $f$ is different than that with $g$, for instance: 60 | $$h \circ f \neq h \circ g$$ 61 | then we can directly "observe" the difference between $f$ and $g$. But even if the difference is not directly observable, we might use functors to zoom in on the hom-set. A functor $F$ may map the two morphisms to distinct morphisms: 62 | $$F f \neq F g$$ 63 | in a richer category, where the abutting hom-sets provide more resolution, e.g., 64 | $$h' \circ F f \neq h' \circ F g$$ 65 | where $h'$ is not in the image of $F$. 66 | 67 | ## Hom-Set Isomorphisms 68 | 69 | A lot of categorical constructions rely on isomorphisms between hom-sets. But since hom-sets are just sets, a plain isomorphism between them doesn't tell you much. For finite sets, an isomorphism just says that they have the same number of elements. If the sets are infinite, their cardinality must be the same. But any meaningful isomorphism of hom-sets must take into account composition. And composition involves more than one hom-set. We need to define isomorphisms that span whole collections of hom-sets, and we need to impose some compatibility conditions that interoperate with composition. And a [*natural*]{.keyword #natural}\index{natural} isomorphism fits the bill exactly. 70 | 71 | But what's a natural isomorphism of hom-sets? Naturality is a property of mappings between functors, not sets. So we are really talking about a natural isomorphism between hom-set-valued functors. These functors are more than just set-valued functors. Their action on morphisms is induced by the appropriate hom-functors. Morphisms are canonically mapped by hom-functors using either pre- or post-composition (depending on the covariance of the functor). 72 | 73 | The Yoneda embedding is one example of such an isomorphism. It maps hom-sets in $\cat{C}$ to hom-sets in the functor category; and it's natural. One functor in the Yoneda embedding is the hom-functor in $\cat{C}$ and the other maps objects to sets of natural transformations between hom-sets. 74 | 75 | The definition of a limit is also a natural isomorphism between hom-sets (the second one, again, in the functor category): 76 | $$\cat{C}(c, \Lim{D}) \simeq \Nat(\Delta_c, D)$$ 77 | It turns out that our construction of an exponential object, or that of a free monoid, can also be rewritten as a natural isomorphism between hom-sets. 78 | 79 | This is no coincidence --- we'll see next that these are just different examples of adjunctions, which are defined as natural isomorphisms of hom-sets. 80 | 81 | ## Asymmetry of Hom-Sets 82 | 83 | There is one more observation that will help us understand adjunctions. Hom-sets are, in general, not symmetric. A hom-set $\cat{C}(a, b)$ is often very different from the hom-set $\cat{C}(b, a)$. The ultimate demonstration of this asymmetry is a partial order viewed as a category. In a partial order, a morphism from $a$ to $b$ exists if and only if $a$ is less than or equal to $b$. If $a$ and $b$ are different, then there can be no morphism going the other way, from $b$ to $a$. So if the hom-set $\cat{C}(a, b)$ is non-empty, which in this case means it's a singleton set, then $\cat{C}(b, a)$ must be empty, unless $a = b$. The arrows in this category have a definite flow in one direction. 84 | 85 | A preorder, which is based on a relation that's not necessarily antisymmetric, is also "mostly" directional, except for occasional cycles. It's convenient to think of an arbitrary category as a generalization of a preorder. 86 | 87 | A preorder is a thin category --- all hom-sets are either singletons or empty. We can visualize a general category as a "thick" preorder. 88 | 89 | ## Challenges 90 | 91 | 1. 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$? 92 | -------------------------------------------------------------------------------- /english/part2/ch01.md: -------------------------------------------------------------------------------- 1 | \setcounter{part}{1} 2 | \setcounter{chapter}{10} 3 | \part{} 4 | 5 | # Declarative Programming 6 | 7 | In the first part of the book I argued that both category theory and programming are about composability. In programming, you keep decomposing a problem until you reach the level of detail that you can deal with, solve each subproblem in turn, and re-compose the solutions bottom-up. There are, roughly speaking, two ways of doing it: by telling the computer what to do, or by telling it how to do it. One is called declarative and the other imperative. 8 | 9 | You can see this even at the most basic level. Composition itself may be defined declaratively; as in, `h` is a composite of `g` after `f`: 10 | 11 | ```haskell 12 | h = g . f 13 | ``` 14 | 15 | \noindent 16 | or imperatively; as in, call `f` first, remember the result of that call, then call `g` with the result: 17 | 18 | ```haskell 19 | h x = let y = f x 20 | in g y 21 | ``` 22 | 23 | \noindent 24 | The imperative version of a program is usually described as a sequence of actions ordered in time. In particular, the call to `g` cannot happen before the execution of `f` completes. At least, that's the conceptual picture — in a lazy language, with *call-by-need* argument passing, the actual execution may proceed differently. 25 | 26 | In fact, depending on the cleverness of the compiler, there may be little or no difference between how declarative and imperative code is executed. But the two methodologies differ, sometimes drastically, in the way we approach problem solving and in the maintainability and testability of the resulting code. 27 | 28 | The main question is: when faced with a problem, do we always have the choice between a declarative and imperative approaches to solving it? And, if there is a declarative solution, can it always be translated into computer code? The answer to this question is far from obvious and, if we could find it, we would probably revolutionize our understanding of the universe. 29 | 30 | Let me elaborate. There is a similar duality in physics, which either points at some deep underlying principle, or tells us something about how our minds work. Richard Feynman mentions this duality as an inspiration in his own work on quantum electrodynamics. 31 | 32 | There are two forms of expressing most laws of physics. One uses local, or infinitesimal, considerations. We look at the state of a system around a small neighborhood, and predict how it will evolve within the next instant of time. This is usually expressed using differential equations that have to be integrated, or summed up, over a period of time. 33 | 34 | Notice how this approach resembles imperative thinking: we reach the final solution by following a sequence of small steps, each depending on the result of the previous one. In fact, computer simulations of physical systems are routinely implemented by turning differential equations into difference equations and iterating them. This is how spaceships are animated in the asteroids game. At each time step, the position of a spaceship is changed by adding a small increment, which is calculated by multiplying its velocity by the time delta. The velocity, in turn, is changed by a small increment proportional to acceleration, which is given by force divided by mass. 35 | 36 | `\begin{figure}[H] \centering`{=latex} 37 | ![](images/asteroids.png){width=50%} 38 | `\end{figure}`{=latex} 39 | \noindent 40 | These are the direct encodings of the differential equations corresponding to Newton's laws of motion: 41 | $$ 42 | \begin{aligned} 43 | F &= m \frac{\mathrm{d}v}{\mathrm{d}t} \\ 44 | v &= \frac{\mathrm{d}x}{\mathrm{d}t} 45 | \end{aligned} 46 | $$ 47 | Similar methods may be applied to more complex problems, like the propagation of electromagnetic fields using Maxwell's equations, or even the behavior of quarks and gluons inside a proton using lattice QCD (quantum chromodynamics). 48 | 49 | This local thinking combined with discretization of space and time that is encouraged by the use of digital computers found its extreme expression in the heroic attempt by Stephen Wolfram to reduce the complexity of the whole universe to a system of cellular automata. 50 | 51 | The other approach is global. We look at the initial and the final state of the system, and calculate a trajectory that connects them by minimizing a certain functional. The simplest example is the Fermat's principle of least time. It states that light rays propagate along paths that minimize their flight time. In particular, in the absence of reflecting or refracting objects, a light ray from point $A$ to point $B$ will take the shortest path, which is a straight line. But light propagates slower in dense (transparent) materials, like water or glass. So if you pick the starting point in the air, and the ending point under water, it's more advantageous for light to travel longer in the air and 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: 52 | $$\frac{\sin\theta_1}{\sin\theta_2} = \frac{v_1}{v_2}$$ 53 | where $v_1$ is the speed of light in the air and $v_2$ is the speed of light in the water. 54 | 55 | `\begin{figure}[H] \centering`{=latex} 56 | ![](images/snell.jpg){width=30%} 57 | `\end{figure}`{=latex} 58 | \noindent 59 | All of classical mechanics can be derived from the principle of least action. The action can be calculated for any trajectory by integrating the Lagrangian, which is the difference between kinetic and potential energy (notice: it's the difference, not the sum — the sum would be the total energy). When you fire a mortar to hit a given target, the projectile will first go up, where the potential energy due to gravity is higher, and spend some time there racking up negative contribution to the action. It will also slow down toward the top of the parabola, to minimize kinetic energy. Then it will speed up to go quickly through the area of low potential energy. 60 | 61 | `\begin{figure}[H] \centering`{=latex} 62 | ![](images/mortar.jpg){width=35%} 63 | `\end{figure}`{=latex} 64 | \noindent 65 | Feynman's greatest contribution was to realize that the principle of least action can be generalized to quantum mechanics. There, again, the problem is formulated in terms of initial state and final state. The Feynman path integral between those states is used to calculate the probability of transition. 66 | 67 | `\begin{figure}[H] \centering`{=latex} 68 | ![](images/feynman.jpg){width=35%} 69 | `\end{figure}`{=latex} 70 | \noindent 71 | The point is that there is a curious unexplained duality in the way we can describe the laws of physics. We can use the local picture, in which things happen sequentially and in small increments. Or we can use the global picture, where we declare the initial and final conditions, and everything in between just follows. 72 | 73 | The global approach can be also used in programming, for instance when implementing ray tracing. We declare the position of the eye and the positions of light sources, and figure out the paths that the light rays may take to connect them. We don't explicitly minimize the time of flight for each ray, but we do use Snell's law and the geometry of reflection to the same effect. 74 | 75 | The biggest difference between the local and the global approach is in their treatment of space and, more importantly, time. The local approach embraces the immediate gratification of here and now, whereas the global approach takes a long-term static view, as if the future had been preordained, and we were only analyzing the properties of some eternal universe. 76 | 77 | Nowhere is it better illustrated than in the Functional Reactive Programming approach to user interaction. Instead of writing separate handlers for every possible user action, all having access to some shared mutable state, FRP treats external events as an infinite list, and applies a series of transformations to it. Conceptually, the list of all our future actions is there, available as the input data to our program. From a program's perspective there's no difference between the list of digits of $\pi$, a list of pseudo-random numbers, or a list of mouse positions coming through computer hardware. In each case, if you want to get the $n^\text{th}$ item, you have to first go through the first $n-1$ items. When applied to temporal events, we call this property *causality*. 78 | 79 | So what does it have to do with category theory? I will argue that category theory encourages a global approach and therefore supports declarative programming. First of all, unlike calculus, it has no built-in notion of distance, or neighborhood, or time. All we have is abstract objects and abstract connections between them. If you can get from $A$ to $B$ through a series of steps, you can also get there in one leap. Moreover, the major tool of category theory is the universal construction, which is the epitome of a global approach. We've seen it in action, for instance, in the definition of the categorical product. It was done by specifying its properties — a very declarative approach. It's an object equipped with two projections, and it's the best such object — it optimizes a certain property: the property of factorizing the projections of other such objects. 80 | 81 | `\begin{figure}[H] \centering`{=latex} 82 | ![](images/productranking.jpg){width=35%} 83 | `\end{figure}`{=latex} 84 | \noindent 85 | Compare this with Fermat's principle of minimum time, or the principle of least action. 86 | 87 | Conversely, contrast this with the traditional definition of a Cartesian product, which is much more imperative. You describe how to create an element of the product by picking one element from one set and another element from another set. It's a recipe for creating a pair. And there's another for disassembling a pair. 88 | 89 | In almost every programming language, including functional languages like Haskell, product types, coproduct types, and function types are built in, rather than being defined by universal constructions; although there have been attempts at creating categorical programming languages (see, e.g., [Tatsuya Hagino's thesis](http://web.sfc.keio.ac.jp/~hagino/thesis.pdf)^[]). 90 | 91 | Whether used directly or not, categorical definitions justify pre-existing programming constructs, and give rise to new ones. Most importantly, category theory provides a meta-language for reasoning about computer programs at a declarative level. It also encourages reasoning about problem specification before it is cast into code. 92 | -------------------------------------------------------------------------------- /english/part3/ch03.md: -------------------------------------------------------------------------------- 1 | # Free/Forgetful Adjunctions {#freeforgetful-adjunctions} 2 | 3 | 4 | 5 | Free constructions are a powerful application of adjunctions. A [*free functor*]{.keyword #free_functor}\index{free functor} is defined as the left adjoint to a [*forgetful functor*]{.keyword #forgetful_functor2}\index{forgetful 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 objects often carry the memory of sets, in the sense that there is a mapping --- a functor --- from a given category $\cat{C}$ to $\Set$. A set corresponding to some object in $\cat{C}$ is called its [*underlying set*]{.keyword #underlying_set}\index{underlying set}. 6 | 7 | Monoids are such objects that have underlying sets --- sets of elements. There is a forgetful functor $U$ from the category of monoids $\cat{Mon}$ to the category of sets, which maps monoids to their underlying sets. It also maps monoid morphisms (homomorphisms) to functions between sets. 8 | 9 | I like to think of $\cat{Mon}$ as having split personality. On the one hand, it's a bunch of sets with multiplication and unit elements. On the other hand, it's a category with featureless objects whose only structure is encoded in morphisms that go between them. Every set-function that preserves multiplication and unit gives rise to a morphism in $\cat{Mon}$. 10 | 11 | Things to keep in mind: 12 | 13 | * There may be many monoids that map to the same set, and 14 | * There are fewer (or at most as many as) monoid morphisms than there are functions between their underlying sets. 15 | 16 | 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](#free-monoids) we've discussed before. 17 | 18 | ![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.](images/forgetful.jpg "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."){width=60%} 19 | 20 | \noindent 21 | In terms of hom-sets, we can write this adjunction as: 22 | $$\cat{Mon}(F x, m) \cong \Set(x, U m)$$ 23 | This (natural in $x$ and $m$) isomorphism tells us that: 24 | 25 | * 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)$. 26 | * 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.) 27 | 28 | `\begin{figure}[H] \centering`{=latex} 29 | ![](images/freemonadjunction.jpg){width=80%} 30 | `\end{figure}`{=latex} 31 | \noindent 32 | The intuition is that $F x$ is the “maximum” monoid that can be built on the basis of $x$. If we could look inside monoids, we would see that any morphism that belongs to $\cat{Mon}(F x, m)$ *embeds* this free monoid in some other monoid $m$. It does it by possibly identifying some elements. In particular, it embeds the generators of $F x$ (i.e., the elements of $x$) in $m$. The adjunction shows that the embedding of $x$, which is given by a function from $\Set(x, U m)$ on the right, uniquely determines the embedding of monoids on the left, and vice versa. 33 | 34 | In Haskell, the list data structure is a free monoid (with some caveats: see [Dan Doel's blog post](http://comonad.com/reader/2015/free-monoids-in-haskell/)^[]). A list type `[a]` is a free monoid with the type `a` representing the set of generators. For instance, the type `[Char]` contains the unit element --- the empty list `[]` --- and the singletons like `['a']`, `['b']` --- the generators of the free monoid. The rest is generated by applying the “product.” Here, the product of two lists simply appends one to another. Appending is associative and unital (that is, there is a neutral element --- here, the empty list). A free monoid generated by `Char` is nothing but the set of all strings of characters from `Char`. It's called `String` in Haskell: 35 | 36 | ```haskell 37 | type String = [Char] 38 | ``` 39 | 40 | \noindent 41 | (`type` defines a type synonym --- a different name for an existing type). 42 | 43 | Another interesting example is a free monoid built from just one generator. It's the type of the list of units, `[()]`. Its elements are `[]`, `[()]`, `[(), ()]`, etc. Every such list can be described by one natural number --- its length. There is no more information encoded in the list of units. Appending two such lists produces a new list whose length is the sum of the lengths of its constituents. It's easy to see that the type `[()]` is isomorphic to the additive monoid of natural numbers (with zero). Here are the two functions that are the inverse of each other, witnessing this isomorphism: 44 | 45 | ```haskell 46 | toNat :: [()] -> Int 47 | toNat = length 48 | 49 | toLst :: Int -> [()] 50 | toLst n = replicate n () 51 | ``` 52 | 53 | \noindent 54 | For simplicity I used the type `Int` rather than `Natural`, but the idea is the same. The function `replicate` creates a list of length `n` pre-filled with a given value --- here, the unit. 55 | 56 | ## Some Intuitions 57 | 58 | What follows are some hand-waving arguments. Those kind of arguments are far from rigorous, but they help in forming intuitions. 59 | 60 | To get some intuition about the free/forgetful adjunctions it helps to keep in mind that functors and functions are lossy in nature. Functors may collapse multiple objects and morphisms, functions may bunch together multiple elements of a set. Also, their image may cover only part of their codomain. 61 | 62 | An “average” hom-set in $\Set$ will contain a whole spectrum of functions starting with the ones that are least lossy (e.g., injections or, possibly, isomorphisms) and ending with constant functions that collapse the whole domain to a single element (if there is one). 63 | 64 | I tend to think of morphisms in an arbitrary category as being lossy too. It's just a mental model, but it's a useful one, especially when thinking of adjunctions --- in particular those in which one of the categories is $\Set$. 65 | 66 | Formally, we can only speak of morphisms that are invertible (isomorphisms) or non-invertible. It's that latter kind that may be thought of as lossy. There is also a notion of mono- and epi- morphisms that generalize the idea of injective (non-collapsing) and surjective (covering the whole codomain) functions, but it's possible to have a morphism that is both mono and epi, and which is still non-invertible. 67 | 68 | In the Free $\dashv$ Forgetful adjunction, we have the more constrained category $\cat{C}$ on the left, and a less constrained category $\cat{D}$ on the right. Morphisms in $\cat{C}$ are “fewer” because they have to preserve some additional structure. In the case of $\cat{Mon}$, they have to preserve multiplication and unit. Morphisms in $\cat{D}$ don't have to preserve as much structure, so there are “more” of them. 69 | 70 | When we apply a forgetful functor $U$ to an object $c$ in $\cat{C}$, we think of it as revealing the “internal structure” of $c$. In fact, if $\cat{D}$ is $\Set$ we think of $U$ as *defining* the internal structure of $c$ --- its underlying set. (In an arbitrary category, we can't talk about the internals of an object other than through its connections to other objects, but here we are just hand-waving.) 71 | 72 | If we map two objects $c'$ and $c$ using $U$, we expect that, in general, the mapping of the hom-set $\cat{C}(c', c)$ will cover only a subset of $\cat{D}(U c', U c)$. That's because morphisms in $\cat{C}(c', c)$ have to preserve the additional structure, whereas the ones in $\cat{D}(U c', U c)$ don't. 73 | 74 | `\begin{figure}[H] \centering`{=latex} 75 | ![](images/forgettingmorphisms.jpg){width=45%} 76 | `\end{figure}`{=latex} 77 | \noindent 78 | But since an adjunction is defined as an [*isomorphism*]{.keyword #isomorphism}\index{isomorphism} of particular hom-sets, we have to be very picky with our selection of $c'$. In the adjunction, $c'$ is picked not from just anywhere in $\cat{C}$, but from the (presumably smaller) image of the free functor $F$: 79 | $$\cat{C}(F d, c) \cong \cat{D}(d, U c)$$ 80 | The image of $F$ must therefore consist of objects that have lots of morphisms going to an arbitrary $c$. In fact, there has to be as many structure-preserving morphisms from $F d$ to $c$ as there are non-structure preserving morphisms from $d$ to $U c$. It means that the image of $F$ must consist of essentially structure-free objects (so that there is no structure to preserve by morphisms). Such “structure-free” objects are called free objects. 81 | 82 | `\begin{figure}[H] \centering`{=latex} 83 | ![](images/freeimage.jpg){width=45%} 84 | `\end{figure}`{=latex} 85 | \noindent 86 | In the monoid example, a free monoid has no structure other than what's generated by unit and associativity laws. Other than that, all multiplications produce brand new elements. 87 | 88 | In a free monoid, $2 * 3$ is not $6$ --- it's a new element ${[}2, 3{]}$. Since 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 identifications give you different monoids. 89 | 90 | This leads to another interesting intuition: Free monoids, instead of performing the monoidal operation, accumulate the arguments that were passed to it. Instead of multiplying $2$ and $3$ they remember $2$ and $3$ in a list. The advantage of this scheme is that we don't have to specify what monoidal operation we will use. We can keep accumulating arguments, and only at the end apply an operator to the result. And it's then that we can chose what operator to apply. We can add the numbers, or multiply them, or perform addition modulo 2, and so on. A free monoid separates the creation of an expression from its evaluation. We'll see this idea again when we talk about algebras. 91 | 92 | This intuition generalizes to other, more elaborate free constructions. For instance, we can accumulate whole expression trees before evaluating them. The advantage of this approach is that we can transform such trees to make the evaluation faster or less memory consuming. This is, for instance, done in implementing matrix calculus, where eager evaluation would lead to lots of allocations of temporary arrays to store intermediate results. 93 | 94 | ## Challenges 95 | 96 | 1. 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$. 97 | -------------------------------------------------------------------------------- /japanese/part3/ch04.md: -------------------------------------------------------------------------------- 1 | # モナド:プログラマーの定義 2 | 3 | プログラマーたちは、モナドにまつわる神話を発展させてきた。それはプログラミングにおける最も抽象的で難しい概念の1つだと考えられている。「理解した」人とそうでない人がいる。多くの人にとって、モナドの概念を理解した瞬間はあたかも神秘的な体験のようだ。モナドは非常に多様な構成の本質を抽象化しているので、日常生活でうまく比喩できるものがない。そして我々は暗闇の中で手探りするようになった。まるで盲人たちが象のさまざまな部分に触れて「ロープだ」「木の幹だ」「ブリトーだ!」と勝ち誇って叫ぶように[^britto]。 4 | 5 | [^britto]: 訳注:もともとの「群盲象を評す」というインドの寓話にはブリトー(小麦粉の薄焼き生地で具材を包んだ料理)は出てこない。モナドがしばしばブリトーに例えられるのには、Brent Yorgeyがブログで「モナドの変な理解の仕方」の例として挙げたのに対し、きちんと理解している人たちが「ブリトーとしてもちゃんと説明できる」とふざけて乗ってきた、という経緯がある。参考: 6 | 7 | * 8 | * 9 | 10 | 誤解を正させてもらおう。モナドを取り巻く神秘主義はすべて誤解に基づいている。モナドはとてもシンプルな概念だ。混乱を引き起こしているのは、モナドの応用先の多様さなのだ。 11 | 12 | この記事のための調査の一環として、私はダクトテープ(別名ダックテープ)とその応用先について調べた。それを使ってできることのほんの一例を紹介しよう。 13 | 14 | * ダクトをシーリングする 15 | * アポロ13号に搭載された二酸化炭素除去装置を修理する 16 | * いぼを治療する 17 | * アップルのiPhone 4の通話切断問題を修正する 18 | * プロムで着るドレスを作る 19 | * 吊り橋を建設する 20 | 21 | 仮にあなたがダクトテープが何か知らず、このリストに基づいて理解しようとしているところを想像してほしい。幸運を祈る! 22 | 23 | そういうわけで、「モナドは……のようなものだ」という常套句のコレクションにもう1つ追加しようと思う。モナドはダクトテープのようなものだ。応用は幅広く多様だが、原理はごく単純だ。モナドは物同士をくっつける。より正確には、物同士を合成する。 24 | 25 | このことは、多くのプログラマー、特に命令型言語をバックグラウンドに持つプログラマーがモナドを理解するのに困難が伴う理由の一部を説明している。問題は、我々がプログラミングを関数合成の観点から考えるのに慣れていないことにある。これはもっともなことだ。関数から関数へ値を直接渡さずに、中間値に名前を付けるのは我々にとってよくあることだ。また、しばしばグルーコードの短い断片を、ヘルパー関数に抽象化せずにインライン化する。以下は、ベクトルの長さを求める関数をC言語で命令型スタイルで実装したものだ。 26 | 27 | ```c 28 | double vlen(double *v) { 29 | double d = 0.0; 30 | int n; 31 | for (n = 0; n < 3; ++n) 32 | d += v[n]* v[n]; 33 | return sqrt(d); 34 | } 35 | ``` 36 | 37 | \noindent 38 | これを、明示的な関数合成を用いた(様式化された)Haskell版と比較してほしい。 39 | 40 | ```haskell 41 | vlen = sqrt . sum . fmap (flip (^) 2) 42 | ``` 43 | 44 | \noindent 45 | (ここでは、より謎めかせるために、指数演算子`(^)`の2番目の引数を`2`に設定して部分適用した^[訳注:普通は、ポイントフリー記法を使う場合でも `sqrt . sum . fmap (^ 2)` または`sqrt . sum . map (^ 2)` とする。]。) 46 | 47 | Haskellのポイントフリースタイルが常に優れていると主張しているのではなく、プログラミングで行うことのすべての基礎に関数合成があると主張しているだけだ。そして実質的には関数を合成しているにもかかわらず、Haskellではわざわざ`do`記法と呼ばれる命令型構文をモナド的な合成のために提供している。その使い方については後で説明する。まずは、そもそもなぜモナド的な合成が必要なのか説明しよう。 48 | 49 | ## クライスリ圏 50 | 51 | 以前、通常の関数を装飾することで[Writerモナド](#writer_monad)(第4章)に到達したのだった。この特定の装飾は、戻り値を文字列と、あるいはもっと一般にはモノイドの要素とペアにすることによってなされた。いまではそのような装飾が関手だと気付ける。 52 | 53 | ```haskell 54 | newtype Writer w a = Writer (a, w) 55 | 56 | instance Functor (Writer w) where 57 | fmap f (Writer (a, w)) = Writer (f a, w) 58 | ``` 59 | 60 | \noindent 61 | 続いて、以下の形式の装飾された関数すなわちクライスリ射 (Kleisli arrow) を合成する方法を発見したのだった。 62 | 63 | ```haskell 64 | a -> Writer w b 65 | ``` 66 | 67 | \noindent 68 | ログの累積は、まさにこの合成の内部で実装されているのだった。 69 | 70 | いまではクライスリ圏をより一般的に定義する準備が完了している。まずは圏$\cat{C}$と自己関手$m$から始める。対応するクライスリ圏$\cat{K}$は$\cat{C}$と同じ対象を持つが、射は異なる。$\cat{K}$内の2つの対象$a$と$b$の間の射は、もとの圏$\cat{C}$内の射 71 | $$a \to m\ b$$ 72 | として実装される。注意すべきは、$\cat{K}$内のクライスリ射は$a$と$b$の間の射として扱い、$a$と$m\ b$の間の射としては扱わないことだ。 73 | 74 | 我々の例においては、ある決まったモノイド`w`について、$m$は`Writer w`に特化されていた。 75 | 76 | クライスリ射は、それらに対し適切な合成を定義できるときだけ圏をなす。合成があって、その合成が結合的かつどの対象についても恒等射を持つ場合、関手$m$は[*モナド*]{.keyword #monad}\index{モナド} (monad) と呼ばれ、その結果形成される圏はクライスリ圏と呼ばれる。 77 | 78 | Haskellでは、クライスリ合成はfish演算子`>=>`を用いて定義され、その恒等射は`return`と呼ばれる多相関数だ。クライスリ合成を使ったモナドの定義は次のとおりだ^[訳注:現在のHaskellでは`Monad`は`Applicative`の派生クラス。`Applicative`では`pure :: a -> f a`が定義されており、`Monad`で`return = pure`以外の定義をすると警告が表示される。]。 79 | 80 | ```haskell 81 | class Monad m where 82 | (>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c) 83 | return :: a -> m a 84 | ``` 85 | 86 | \noindent 87 | モナドを定義する方法には同等のものがいくつもあり、前述のものがHaskellエコシステムでの主要な方法ではないことを覚えておいてほしい。この方法の概念の簡潔さと得られる直観は気に入っているが、プログラミングの際に便利な定義は他にもある。それらについてはすぐに話すつもりだ。 88 | 89 | この定式化ではモナド則を非常に簡単に表現できる。Haskellではモナド則を強制できないが、等式による推論には使える。それらは単にクライスリ圏の標準的な合成律だ。 90 | 91 | ```haskell 92 | (f >=> g) >=> h = f >=> (g >=> h) -- 結合性 93 | return >=> f = f -- 左単位元 94 | f >=> return = f -- 右単位元 95 | ``` 96 | 97 | \noindent 98 | この種の定義はモナドが本当は何なのかも表している。つまり、モナドは装飾された関数を合成する方法なのだ。副作用や状態は関係ない。関係あるのは合成だ。後で見るように、装飾された関数はさまざまな作用や状態を表現するために使えるが、モナドはそのためのものではない。モナドとは、装飾された関数の一端を別の装飾された関数の一端につなぐような粘着力のあるダクトテープなのだ。 99 | 100 | `Writer`の例に戻ろう。ログ生成関数(`Writer`関手に対するクライスリ射)たちは圏をなす。なぜなら、`Writer`はモナドだからだ^[監訳注:本書では簡潔性からか `<>` 演算子には言及がないが、現在のHaskellでは`Data.Semigroup.<>` を用いて`mappend = (<>)` と定義されているので、ここでのコードについては`s <> s'`のように書いたほうがよりストレートだろう。]。 101 | 102 | ```haskell 103 | instance Monoid w => Monad (Writer w) where 104 | f >=> g = \a -> 105 | let Writer (b, s) = f a 106 | Writer (c, s') = g b 107 | in Writer (c, s `mappend` s') 108 | return a = Writer (a, mempty) 109 | ``` 110 | 111 | \noindent 112 | `Writer w`のモナド則は、`w`のモノイド則が満たされている限り満たされる(これもHaskellでは強制できない)。 113 | 114 | `Writer`モナドについて、`tell`と呼ばれる便利なクライスリ射が定義されている。その唯一の目的は引数をログに追加することだ。 115 | 116 | ```haskell 117 | tell :: w -> Writer w () 118 | tell s = Writer ((), s) 119 | ``` 120 | 121 | \noindent 122 | これは後で他のモナド的な関数の構成要素として使うことになる。 123 | 124 | ## Fishの解剖 125 | 126 | さまざまなモナドに対してfish演算子を実装するとすぐ、コードに重複がたくさんあり、簡単に括り出せることに気付くだろう。まず、2つの関数のクライスリ合成は1つの関数を返す必要があるので、その実装も型`a`の引数を1つ取るラムダから始められる。 127 | 128 | ```haskell 129 | (>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c) 130 | f >=> g = \a -> ... 131 | ``` 132 | 133 | \noindent 134 | この引数は`f`に渡す以外のことはできない。 135 | 136 | ```haskell 137 | f >=> g = \a -> let mb = f a 138 | in ... 139 | ``` 140 | 141 | \noindent 142 | ここで、型`m c`の結果を生成する必要がある。そのために自由に使えるのは型`m b`の対象と関数`g :: b -> m c`だ。この関数は*bind*と呼ばれ、通常は中置演算子として書かれる。 143 | 144 | ```haskell 145 | (>>=) :: m a -> (a -> m b) -> m b 146 | ``` 147 | 148 | \noindent 149 | どんなモナドについても、fish演算子を定義する代わりにbindを定義できる。実際、標準的なHaskellのモナドの定義ではbindが使われている。 150 | 151 | ```haskell 152 | class Monad m where 153 | (>>=) :: m a -> (a -> m b) -> m b 154 | return :: a -> m a 155 | ``` 156 | 157 | \noindent 158 | 以下に`Writer`モナドのbindの定義を示す。 159 | 160 | ```haskell 161 | (Writer (a, w)) >>= f = let Writer (b, w') = f a 162 | in Writer (b, w `mappend` w') 163 | ``` 164 | 165 | \noindent 166 | これは確かにfish演算子の定義より短い。 167 | 168 | `m`が関手であるという事実を利用すればbindをさらに詳しく分析できる。`fmap`を使えば`m a`の内容に関数`a -> m b`を適用できる。それによって`a`は`m b`に変換される。したがって、適用結果の型は`m (m b)`となる。これは欲しかったものそのものではない――必要なのは型`m b`の結果だ――が、惜しいところまでは行っている。`m`の2重適用を潰す、つまりフラット化する関数さえあればよい。そのような関数は`join`と呼ばれる。 169 | 170 | ```haskell 171 | join :: m (m a) -> m a 172 | ``` 173 | 174 | \noindent 175 | `join`を使ってbindを次のように書き直せる。 176 | 177 | ```haskell 178 | ma >>= f = join (fmap f ma) 179 | ``` 180 | 181 | \noindent 182 | これはモナドの定義の3番目の選択肢につながる。 183 | 184 | ```haskell 185 | class Functor m => Monad m where 186 | join :: m (m a) -> m a 187 | return :: a -> m a 188 | ``` 189 | 190 | \noindent 191 | ここでは`m`が`Functor`であることを明示的に要求した。これまでの2つのモナドの定義ではその必要はなかった^[監訳注:実際のHaskellでは「その必要はない」ことをコンパイラーに教える手段が(少なくともまだ)ないので、標準的なHaskellのモナドの定義でも`m`が`Functor`であることは(より正確には`Applicative`経由で)明示的に要求される。もっとも、定義は効率を考えなければこの章にあるとおりであるが。]。型構成子`m`は、fish演算子とbind演算子のどちらかをサポートするなら自動的に関手になるからだ。たとえば、`fmap`はbindと`return`で定義できる。 192 | 193 | ```haskell 194 | fmap f ma = ma >>= \a -> return (f a) 195 | ``` 196 | 197 | \noindent 198 | 完全を期すため、`Writer`モナドの`join`を以下に示す^[訳注:`join`も`bind`を用いて`join m = m >>= id`と定義できる。これが上記の定義と一致していることを確認してみよう。]。 199 | 200 | ```haskell 201 | join :: Monoid w => Writer w (Writer w a) -> Writer w a 202 | join (Writer ((Writer (a, w')), w)) = Writer (a, w `mappend` w') 203 | ``` 204 | 205 | ## `do`記法 206 | 207 | モナドを使ってコードを書く方法の1つは、クライスリ射の使用――fish演算子によるそれらの合成だ。このプログラミング手法はポイントフリースタイルを一般化したものだ。ポイントフリーのコードはコンパクトで、実にエレガントなことが多い。しかし、一般には、理解するのが難しくほとんど意味不明だ。だから、ほとんどのプログラマーは関数の引数や中間結果の値に名前を付ける方を好む。 208 | 209 | それはつまり、モナドを扱う場合にはfish演算子よりもbind演算子が好ましいことを意味する。Bindはモナド的な値を取ってモナド的な値を返す。プログラマーはそれらの値に名前を付けることもできる。しかし、これは改善とは言えない。本当にやりたいことは、あたかも通常の値を扱っているかのようなふりであって、それらの値をカプセル化しているモナド的コンテナーを扱いたいのではない。そのことこそ命令型コードの仕組みだ――グローバルなログの更新などの副作用は、ほとんど目に付かないところに隠されている。そしてHaskellが`do`記法でエミュレートするものでもある。 210 | 211 | ここで疑問に思うだろう。一体なぜモナドを使うのか? 副作用を見えなくしたいなら、命令型言語を使い続ければよいのではないか? その答えは、モナドなら副作用をはるかにうまくコントロールできるからだ。たとえば、`Writer`モナドのログは関数から関数へ渡され、グローバルに公開されることはない。ログを改竄したりデータ競合を引き起したりする可能性はない。また、モナド的なコードはプログラムの他の部分から明確に区分され隔離される。 212 | 213 | `do`記法はモナド的な合成のための単なる糖衣構文だ。表面上は命令型コードによく似ているが、bindとラムダ式のシーケンスに直接変換できる。 214 | 215 | 一例として、前に`Writer`モナドでのクライスリ射の合成を説明するために使った例を取り上げる。現在の定義を使うと、それは次のように書き直せる。 216 | 217 | ```haskell 218 | process :: String -> Writer String [String] 219 | process = upCase >=> toWords 220 | ``` 221 | 222 | \noindent 223 | この関数は、動作ログを生成しつつ、入力文字列内のすべての文字を大文字に変換して単語に分割する。 224 | 225 | `do`記法なら以下のようになるだろう。 226 | 227 | ```haskell 228 | process s = do 229 | upStr <- upCase s 230 | toWords upStr 231 | ``` 232 | 233 | \noindent 234 | ここで、`upCase`は`Writer`を生成するにもかかわらず 235 | 236 | ```haskell 237 | upCase :: String -> Writer String String 238 | upCase s = Writer (map toUpper s, "upCase ") 239 | ``` 240 | 241 | \noindent 242 | のように`upStr`は単なる`String`になっている。これは`do`ブロックがコンパイラーによって次のように脱糖されるためだ。 243 | 244 | ```haskell 245 | process s = 246 | upCase s >>= \upStr -> 247 | toWords upStr 248 | ``` 249 | 250 | \noindent 251 | `upCase`のモナド的な結果と、`String`を引数とするラムダとがbindされている。まさにこの引数の名前が`do`ブロックに書かれていた。次の行 252 | 253 | ```haskell 254 | upStr <- upCase s 255 | ``` 256 | 257 | \noindent 258 | は、`upStr`が*得る*のは`upCase s`の結果だ、と読める。 259 | 260 | 擬似的な命令型スタイルは`toWords`をインライン化するとさらに顕著になる。2つの関数呼び出しに置き換えてインライン化しよう。まず`tell`を呼び出して、文字列`"toWords"`をログに記録する。続いて`return`を呼び出して、文字列`upStr`を`words`によって分割した結果を返す。`words`は文字列を扱う通常の関数であることに注意してほしい。 261 | 262 | ```haskell 263 | process s = do 264 | upStr <- upCase s 265 | tell "toWords " 266 | return (words upStr) 267 | ``` 268 | 269 | \noindent 270 | ここで、doブロックの各行を脱糖すると、ネストされた新たなbindが導入される。 271 | 272 | ```haskell 273 | process s = 274 | upCase s >>= \upStr -> 275 | tell "toWords " >>= \() -> 276 | return (words upStr) 277 | ``` 278 | 279 | \noindent 280 | `tell`はunit値を生成するので、後続のラムダに渡す必要はないことに注意してほしい。モナド的な結果の内容を無視する(ただし、その作用――ここではログへの寄与――は無視しない)のはよくあることだ。そのため、そのような場合にbindを置き換える特別な演算子がある。 281 | 282 | ```haskell 283 | (>>) :: m a -> m b -> m b 284 | m >> k = m >>= (\_ -> k) 285 | ``` 286 | 287 | \noindent 288 | 実際に脱糖されたコードは次のようになる。 289 | 290 | ```haskell 291 | process s = 292 | upCase s >>= \upStr -> 293 | tell "toWords " >> 294 | return (words upStr) 295 | ``` 296 | 297 | \noindent 298 | 一般に`do`ブロックは、左矢印によってそれ以降のコードで使える名前を導入するような行や、純粋に副作用を目的として実行される行(またはサブブロック)から構成される。Bind演算子は行間で暗黙的に使われる。ちなみに、Haskellでは`do`ブロックの書式[訳注:改行やインデント]を波括弧とセミコロンで置き換えられる。これが、モナドはセミコロンをオーバーロードする方法だ、と表現される理由になっている。 299 | 300 | `do`記法を脱糖する際にラムダとbind演算子がネストされることで、`do`ブロックの残りを各行の結果に基づいて実行するのに影響を与えることに注目してほしい。この性質は、例外をシミュレートするなど、複雑な制御構造を導入するために使える。 301 | 302 | 興味深いことに、`do`記法と同等のものが命令型言語に、特にC++に応用されている。再開可能な関数 (resumable function) やコルーチン (coroutine) のことだ。C++の[futureがモナドをなす](https://bartoszmilewski.com/2014/02/26/c17-i-see-a-monad-in-your-future/)^[] ことは秘密ではない。それは継続モナドの一例だ。継続モナドについてはすぐ後で議論する。継続の問題点は、合成するのが非常に難しいことだ。Haskellでは`do`という表記法を使うことで、「こっちのハンドラーがそっちのハンドラーを呼ぶ」というスパゲッティを、逐次コードに非常によく似たものに変換している。再開可能な関数によって、同じ変換がC++でも可能になる。 303 | また、同じメカニズムを適用すれば、[ネストされたループのスパゲッティ](https://bartoszmilewski.com/2014/04/21/getting-lazy-with-c/)^[] をリスト内包表記または「ジェネレーター」に変えられる。これは本質的にリストモナドの`do`記法だ。モナドによる統一的な抽象化がなければ、これらの個々の問題は通常、その問題に特化した拡張を言語に提供することで対処されることになる。Haskellでは、すべてライブラリーを通じて対処される。 304 | --------------------------------------------------------------------------------