├── diagram1.2a.jpg ├── diagram1.2b.jpg ├── diagram1.2c.jpg ├── diagram1.2d.jpg ├── README.md ├── CategoryTheory1.1.md ├── STLC.hs └── CategoryTheory1.2.md /diagram1.2a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BartoszMilewski/CategoryTheory/HEAD/diagram1.2a.jpg -------------------------------------------------------------------------------- /diagram1.2b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BartoszMilewski/CategoryTheory/HEAD/diagram1.2b.jpg -------------------------------------------------------------------------------- /diagram1.2c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BartoszMilewski/CategoryTheory/HEAD/diagram1.2c.jpg -------------------------------------------------------------------------------- /diagram1.2d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BartoszMilewski/CategoryTheory/HEAD/diagram1.2d.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bartosz Milewski - Category Theory 2 | 3 | This repository contains notes for Bartosz Milewski's lectures on Category Theory, which you can find on [Youtube](https://www.youtube.com/playlist?list=PLbgaMIhjbmEnaH_LTkxLI7FMa2HsnawM_). 4 | 5 | If anyone wants to join in feell free. To keep it quick I am thinking of screenshotting the diagrams, but if anyone feels like converting them to LaTeX format or similar, please do so! 6 | 7 | Lecture notes so far: 8 | 9 | * [1.1: Motivation and Philosophy](CategoryTheory1.1.md) 10 | -------------------------------------------------------------------------------- /CategoryTheory1.1.md: -------------------------------------------------------------------------------- 1 | #Lecture 1.1 - Motivation and Philosophy 2 | 3 | [00:00](https://youtu.be/I8LbkfSSR58) 4 | 5 | Posing question: What has category theory got to do with programming? 6 | 7 | Assembly language is a very imperative approach telling the computer precisely what to do. Assembly language related to Turing Machines. 8 | 9 | Assembly is one approach to programming, the other approach coming from Mathematics, e.g. Alonzo Church. 10 | 11 | Impractical to write assembly programs, so abstraction is needed. Next level is procedural programming. Dividing problems into procedures. 12 | 13 | Next level of abstraction is Object Oriented, hiding stuff inside objects, allowing you to forget about the implementation and deal with a bigger picture. 14 | 15 | To deal with more complex problem you need to chop problems into smaller problems. This is Composability. 16 | 17 | Abstraction means subtraction - getting rid of details. E.g. In OO objects hide details. 18 | 19 | Concurrency doesn't mix well with OO programming. Because objects hide two things that are important - mutation and sharing. Mixing sharing and mutation means it is abstracting over data races. Locks don't help much either. 20 | 21 | Next level of abstraction is over functions. 22 | 23 | In C++ template programming is the highest level of abstraction. Very complex in C++ - but they are based on simple ideas in Haskell. 24 | 25 | Even in Haskell some things are awkward to express. E.g. Edward Kmett libraries that seem hard to understand, but they are based on ideas in category theory that are harder to express in Haskell. 26 | 27 | Category theory is a higher-level language above other languages like Haskell, C++, Scala, and ideas can be translated into these. In the same way that Haskell is a higher-level language compared to C++, and Haskell ideas can be translated into C++. 28 | 29 | [22:41](https://youtu.be/I8LbkfSSR58?t=1301) 30 | 31 | There is a theoretical motivation to study Cateogry Theory, because it makes a lot of programming ideas look the same. And beyond that Category Theory makes a lot of separate parts of Mathematics looks the same - set theory, algebra, topology etc. 32 | 33 | There is Type theory in computer science and Type theory in mathematics. 34 | 35 | Curry-Howard- Lambek Isomorpishm: whatever you do in Logic can be direct translated to something you do in Type theory ... and again to anything you do in Cartesian Complete Categories. 36 | 37 | Some Mathematicians see this as we are discovering something deep truth, but Bartosz thinks there is a simpler explanation based on evolution. 38 | 39 | We are well evolved for image processing due to the pressing need to tell allies from enemies, but only for the last 'millisecond' of evolution have we evolved the ability to think - and more for social and hunting rather than programming and mathematics. 40 | 41 | The only way we know how to deal with complex problems is by decomposing them. In science and mathematics, we can only see problems that can be chopped into pieces and put back. No wonder they all look the same. If the problem isn't choppable we move onto something else! 42 | 43 | In physics, we chop things into pieces, e.g. things are made of atoms - but what is inside the atom? Protons, electrons, etc. We should be able to find a point if we keep chopping. But we can't deal with point particles because things can't get infinitely close. String theory deals with this but it is not choppable. 44 | 45 | In conclusion, maybe category theory is more about how our minds work than about mathematics. It is an epistemology rather than ontology. 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /STLC.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE GADTs #-} 2 | {-# LANGUAGE RankNTypes #-} 3 | {-# LANGUAGE DataKinds #-} 4 | {-# LANGUAGE TypeOperators #-} 5 | {-# LANGUAGE ScopedTypeVariables #-} 6 | {-# LANGUAGE KindSignatures #-} 7 | {-# LANGUAGE TypeFamilies #-} 8 | 9 | module STLC where 10 | 11 | {- From Derek Elkins 12 | 13 | Attached is some Haskell code to compile the STLC to categorical combinators 14 | of a Cartesian closed category and pretty print that as executable code 15 | (using (&&&) from Control.Arrow). 16 | The Haskell code will take an extra argument corresponding to the context 17 | and () should suffice for any closed term. 18 | Prim can lead to broken generated Haskell. 19 | There's an extra swap that makes the generated code look ugly because 20 | Haskell's curry takes things in an inconvenient order. 21 | The code could be made to look a little nicer by defining some helpers 22 | e.g. "swap" and "eval = uncurry id". 23 | 24 | -} 25 | 26 | import Control.Arrow -- for testing 27 | 28 | data Var :: [*] -> * -> * where 29 | Here :: Var (a:as) a 30 | There :: Var as b -> Var (a:as) b 31 | 32 | {- 33 | These types are sort of backwards. 34 | An STLC expression is given a type 35 | and that type is backpropagated. From 36 | Lam (Var Here) :: STLC '[] (a -> a) 37 | which encodes 38 | \x:a -> x 39 | we can deduce that (Var Here) is 40 | STLC (a:'[]) a 41 | which was constructed using 42 | Here :: Var (a:'[]) a 43 | 44 | -} 45 | 46 | data STLC :: [*] -> * -> * where 47 | Var :: Var v a -> STLC v a 48 | App :: STLC v (a -> b) -> STLC v a -> STLC v b 49 | Lam :: STLC (a:v) b -> STLC v (a -> b) 50 | Prj1 :: STLC v (a, b) -> STLC v a 51 | Prj2 :: STLC v (a, b) -> STLC v b 52 | Pair :: STLC v a -> STLC v b -> STLC v (a, b) 53 | Unit :: STLC v () 54 | Prim :: String -> STLC v a 55 | 56 | data CCC :: * -> * -> * where 57 | -- ! :: a -> () 58 | Bang :: CCC a () 59 | -- π₁ :: (a, b) -> a 60 | Pi1 :: CCC (a, b) a 61 | -- π₂ :: (a, b) -> a 62 | Pi2 :: CCC (a, b) b 63 | -- tuple :: (c -> a) -> (c -> b) -> (c -> (a, b)) 64 | Tuple :: CCC c a -> CCC c b -> CCC c (a, b) 65 | -- eval :: (a -> b, a) -> b 66 | Eval :: CCC (a -> b, a) b 67 | -- curry :: ((a, b) -> c) -> (a -> (b -> c)) 68 | Curry :: CCC (a, b) c -> CCC a (b -> c) 69 | -- id :: a -> a 70 | Id :: CCC a a 71 | -- ∘ :: (b -> c) -> (a -> b) -> (a -> c) 72 | O :: CCC b c -> CCC a b -> CCC a c 73 | -- primitive 74 | Arr :: String -> CCC a b 75 | 76 | instance Show (CCC a b) where 77 | showsPrec _ Bang = ("(const ())"++) 78 | showsPrec _ Pi1 = ("fst"++) 79 | showsPrec _ Pi2 = ("snd"++) 80 | showsPrec n (Tuple x y) = showParen (n > 0) $ showsPrec 1 x . (" &&& "++) . showsPrec 1 y 81 | showsPrec _ Eval = ("(uncurry ($))"++) 82 | showsPrec n (Curry f) = showParen (n > 0) $ ("curry "++) . showsPrec 1 f 83 | showsPrec _ Id = ("id"++) 84 | showsPrec n (f `O` g) = showParen (n > 0) $ showsPrec 1 f . (" . "++) . showsPrec 1 g 85 | showsPrec _ (Arr s) = ("const "++) . (s++) 86 | 87 | -- Turns a list of types into a (nested) tuple type 88 | type family Context (v :: [*]) :: * where 89 | Context '[] = () 90 | Context (t:ts) = (t, Context ts) 91 | 92 | -- Produces an arrow from context to a 93 | compile :: STLC v a -> CCC (Context v) a 94 | 95 | compile (Var v) = lookupVar v 96 | compile (App f x) = Eval `O` Tuple (compile f) (compile x) 97 | compile (Lam f) = Curry (compile f `O` swap) 98 | where swap = Tuple Pi2 Pi1 99 | compile (Prj1 p) = Pi1 `O` compile p 100 | compile (Prj2 p) = Pi2 `O` compile p 101 | compile (Pair x y) = Tuple (compile x) (compile y) 102 | compile Unit = Bang 103 | compile (Prim s) = Arr s 104 | 105 | -- returns an arrow that is a composition of Pi1 after zero or more Pi2s 106 | lookupVar :: Var v a -> CCC (Context v) a 107 | lookupVar Here = Pi1 -- Here :: Var (a:as) a 108 | lookupVar (There v) = lookupVar v `O` Pi2 -- `O` is composition 109 | 110 | -- \x -> x 111 | example1 :: forall a. CCC () (a -> a) 112 | example1 = compile (Lam (Var Here) :: STLC '[] (a -> a)) 113 | 114 | tuple :: (a -> b) -> (a -> b') -> (a -> (b, b')) 115 | tuple f g = \a -> (f a, g a) 116 | 117 | f1 :: a -> b -> b 118 | f1 = curry (fst . swap) 119 | 120 | -- \x y -> x + y 121 | -- \x (\ y -> (+ x) y) 122 | ex2 :: STLC '[] (Int -> Int -> Int) 123 | ex2 = Lam 124 | (Lam 125 | (App 126 | (App (Prim "(+)") 127 | (Var (There Here)) 128 | ) 129 | (Var Here) 130 | ) 131 | ) 132 | {- 133 | Lam :: STLC (Int:'[]) (Int -> Int) -> STLC '[] (Int -> (Int -> Int)) 134 | Lam :: STLC (Int:Int:'[]) Int -> STLC (Int:'[]) (Int -> Int) 135 | App :: STLC (Int:Int:'[]) (a -> Int) 136 | -> STLC (Int:Int:'[]) a -> STLC (Int:Int:'[]) Int 137 | App :: STLC (Int:Int:'[]) (a -> (a -> Int)) 138 | -> STLC (Int:Int:'[]) a -> STLC (Int:Int:'[]) (a -> Int) 139 | Prim :: "(+)" -> STLC (Int:Int:'[]) (a -> (a -> Int)) 140 | Var :: Var (Int:Int:'[]) a -> STLC (Int:Int:'[]) a 141 | There :: Var (Int:'[]) a -> Var (Int:Int:'[]) a 142 | Here :: (Int:'[]) a [This unifies a with Int] 143 | Var :: Var (Int:Int:'[]) a -> STLC (Int:Int:'[]) a 144 | Here :: Var (Int:Int:'[]) a. [This also unifies a with Int] 145 | -} 146 | 147 | example2 :: forall a. CCC () (Int -> Int -> Int) 148 | example2 = compile ex2 149 | 150 | eval = uncurry id 151 | swap = snd &&& fst 152 | 153 | f2 :: Num b => a -> b -> b -> b 154 | f2 = curry ((curry ((eval . ((eval . (const (+) &&& (fst . snd))) &&& fst)) . 155 | swap)) . 156 | swap) 157 | 158 | main = print example1 159 | -------------------------------------------------------------------------------- /CategoryTheory1.2.md: -------------------------------------------------------------------------------- 1 | #Lecture 1.2 - What is a category? 2 | 3 | [00:00](https://youtu.be/p54Hd7AmVFU) 4 | 5 | The major tools in our arsenal 6 | 7 | * **Abstraction** 8 | * **Composition** 9 | * **Identity** 10 | 11 | Abstraction is to get rid of unnecessary details. Things that were different because of unnecessary details are now identical. 12 | 13 | Composition and Identity together are defined in a Category. 14 | 15 | Categories have: 16 | 17 | 1. A 'bunch' of objects. 18 | 2. Morphisms, i.e. 'arrows' between two objects. 19 | 20 | (Plus a composition operator, identity morphisms and associativity law, introduced later in the lecture) 21 | 22 | The 'bunch' of objects can be a set, but it doesn't necessarily have to be. This is because there are objects that are bigger than sets1 and categories can be defined for these classes too. 23 | 24 | From a Category Theory point of view, we cannot know what an object is. An object is no properties or internal structure. It is like a 'point'. Similarly for morphisms we cannot know it's internal structure, and the only properties we know is the beginning and end object of the arrow. 25 | 26 | [14:00](https://youtu.be/p54Hd7AmVFU?t=820) 27 | 28 | There are many possibilities related to how arrows can exist between objects: 29 | 30 | ![Diagram 1.2a](diagram1.2a.jpg) 31 | 32 | * Looking at any 2 objects a, b we can see that there may be zero, 1, finite, countable or un-countably infinitely many arrows connecting them in the direction a → b. 33 | * You can (but not necessarily) have arrows going back from b → a. 34 | * And of course, you can have arrows from a → a. 35 | * In this sense a category is like a graph, but it can have infinitely many objects and infinitely many arrows. Or in the other extreme, no objects at all! 36 | 37 | # Composition 38 | 39 | [16:20](https://youtu.be/p54Hd7AmVFU?t=980) 40 | 41 | ![Diagram 1.2b](diagram1.2b.jpg) 42 | 43 | Given any morphisms f : a → b and g : b → c, you can compose them g ∘ f : a → c and is also a morphism in the category. 44 | 45 | Of course there may (or may not) be other different morphisms x, y, z : a → c, as shown by red arrows above. 46 | 47 | You could think of composition as a multiplication table that for any two arrows, you define what is the composition. 48 | 49 | #Identity 50 | 51 | [20:30](https://youtu.be/p54Hd7AmVFU?t=1230) 52 | 53 | ![Diagram 1.2c](diagram1.2c.jpg) 54 | 55 | For every object a there is an arrow id : a → a that is the identity. Denoted Ida 56 | 57 | For all f : a → b, idb ∘ f = f (left identity) 58 | For all g : a → b, g ∘ ida = g (right identity) 59 | 60 | #Associativity 61 | 62 | [23:12](https://youtu.be/p54Hd7AmVFU?t=1392) 63 | 64 | ![Diagram 1.2d](diagram1.2d.jpg) 65 | 66 | Given f : a → b, g: b → c, h: c → d, you can compose two ways: 67 | 68 | * Either compose g ∘ f, then compose the result with h i.e. h ∘ (g ∘ f) 69 | * Or compose h ∘ g, then compose f with the result i.e. (h ∘ g) ∘ f 70 | 71 | Associativity requires that these always be equal for all morphisms f, g, and h. 72 | 73 | I.e. For all f, g, h, h ∘ (g ∘ f) = (h ∘ g) ∘ f 74 | 75 | What if we didn't have this law? Some mathematicians are looking into theories where the law is weakened so that is it true up to isomorpishm. 76 | 77 | # Small Categories vs Large Categories, Groupoids 78 | 79 | [28:27](https://youtu.be/p54Hd7AmVFU?t=1707) 80 | 81 | In general objects don't for a set. If objects form a set we call it small, if the objects do not form a set we call it large. The morphisms between two objects do form a set in the categories we talk about. However in "higher order" categories the morpishms between two objects may not form a set. But we will not talk about such categories. 82 | 83 | A category is not necessarily a group, but if every arrow has an inverse it is called a groupoid. It is more general than a group because a group is a category in which there is only one object, and arrows between them. However a groupoid can have multiple objects meaning that not every pair of morphisms will necessrily compose. 84 | 85 | # Categories in Programming, Set 86 | 87 | [31:46](https://youtu.be/p54Hd7AmVFU?t=1906) 88 | 89 | A single argument function takes an argument of type a and returns a result of type b. So a function is an arrow between these two types. This gives a category where types are the objects and functions are morphisms. 90 | 91 | In Haskell it is a little bit more complicated due to lazyness. Every type has an additional value called bottom (or undefined). Therefore in Haskell, types form a category if you ignore bottom. 92 | 93 | A model for types is they are sets of values. Therefore we can also think of the category as a category of sets, with mathematical functions between them. The category of all sets and functions between them is called Set. 94 | 95 | When viewing Sets and functions we are aware of elements in the set, how functions map elements, etc. However when viewing Set as a category, we no longer have this information, and we just know about objects with no further structure like an atom. 96 | 97 | Composition of functions is defined in terms of how an element is mapped through the two functions being composed. g ∘ f will take elements from the domain set of f and apply f, and then apply g giving an element in the comdomain of g. Using this definition, we create the multiplication table of how morphisms compose in Set. However we then forget these details once dealing with the category. 98 | 99 | The usual identity function for sets becomes the category identity function. 100 | 101 | We can identify things just looking at the morphisms, e.g. is a set empty? This can be defined purely in terms of morphisms without referencing the underlying set structure. There are lots of properties of sets that can be defined in terms of the morphisms, giving a more abstract way of looking at things. 102 | 103 | This is the ultimate in data hiding! 104 | 105 | 106 | [1] For example the set of all sets that are not members of itself. This can't exist. See [Russell's Paradox](https://en.wikipedia.org/wiki/Russell's_paradox) and [Barber Paradox](https://en.wikipedia.org/wiki/Barber_paradox) for more details. 107 | --------------------------------------------------------------------------------