From fc9edfe61c71984b89b8a9ce7bddd3b361f8cf75 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 17:18:56 -0800 Subject: [PATCH 01/19] announcement --- Announcement.md | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ quiver.gif | Bin 0 -> 1939 bytes 2 files changed, 151 insertions(+) create mode 100644 Announcement.md create mode 100644 quiver.gif diff --git a/Announcement.md b/Announcement.md new file mode 100644 index 0000000..3015e37 --- /dev/null +++ b/Announcement.md @@ -0,0 +1,151 @@ +# Announcing free-categories + +## motivation + +The `Category` typeclass in Haskell apparently doesn't +get much use which is a real shame. But many Haskellers +are familiar with it. + +```Haskell +class Category c where + id :: c x x + (.) :: c y z -> c x y -> c x z +``` + +Instances include `(->)`, the category of Haskell types and functions, +and `Kleisli`, the Kleisli category of a `Monad`. + +In Squeal, there's another instance, `Definition`, the category of +database schemas and DDL statements (`CREATE`, `DROP` and `ALTER`). + +For a while I was puzzling on how to add migration support to Squeal. +Support for DDL gets you a long way, but not the whole way. +As a first pass, you can say your migration system is just `Definition`s +with the `Category` instance allowing you to chain your migrations +together. But, a migration system needs to track which `Definition` has +been run in the past and skip it. That means you need to be able +to do some processing on each `Definition` in your chain. Composing +the `Definition`s smashes them together into a single `Definition`. +I needed a data structure that held a list of `Definition`s that can be +but are not yet composed. + +``` +data Path p x y where + Done :: Path p x x + (:>>) :: p x y -> Path p y z -> Path p x z +``` + +This covered my need and also conveniently solved another problem. +Squeal also supported `WITH` statements, however, they had a problem. +As I had typed them, I used a heterogeneous list to contain +the common table expressions. This meant that each CTE had to reference +the same underlying schema and could not therefore reference previous +CTEs in the list. Using a `Path` instead fixed that problem, allowing +each step to append to the schema. + +## previous + +At this point, it was clear this was a cool little data structure +since it solved two different problems. + +So I looked around for this datatype and I remembered a paper, +[Reflection without Remorse](http://okmij.org/ftp/Haskell/zseq.pdf), +written by Atze van der Ploeg and Oleg Kiselyov. They used `Path`s +of `Kleisli` for efficient monadic reflection. They also introduce +isomorphic datatypes to `Path`. +The paper (Kleisli Arrows of Outrageous Fortune) +[https://personal.cis.strath.ac.uk/conor.mcbride/Kleisli.pdf] +written by Conor McBride also uses `Path`, even naming it so. + +A couple of libraries also had it. A support library for reflection +without remorse [type-aligned](https://github.com/atzeus/type-aligned) +existed. Also the library +[free-category](https://github.com/coot/free-category) which took +those ideas a bit further. + +But I come from the land of category theory, and code wasn't really +clarifying to me what this structure was and how it related to +other similar datatypes. It turned out that in mathematics, the +free category was related to something I had studied in my earlier days. +My advisor wrote a [book] +(https://www.amazon.com/Representations-Varieties-Graduate-Studies-Mathematics/dp/1470423073) +about them! + +## quivers + +Like all "free" constructions from the land of category theory, +the free category was a left adjoint to a "forgetful" functor. +That forgetful functor forgot the category structure leaving behind +a "quiver". + +A quiver is like a pre-category. Like categories have objects and +morphisms, a quiver has vertices and arrows, but it doesn't have +to have identities or composition and there are no laws. So, a quiver +is a graph. It's a directed graph, or digraph, because the edges are arrows +and have a direction. Sometimes it's called a multi-digraph, because +there may be multiple arrows between vertices. + +![quiver](quiver.gif) + +In math, quivers are usually studied in the context of representation +theory and algebraic geometry so I was a bit shocked to see them +in programming in a very different context. + +A Haskell quiver is a higher kinded type, + +`p :: k -> k -> Type` + + * where vertices are types `x :: k`, + * and arrows from `x` to `y` are terms `p :: p x y`. + +Lots of familiar things in Haskell are quivers, including all +instances of `Category`, `Arrow`, `Bifunctor` and `Profunctor`. +Haskell quivers aren't as general as the quivers from category +theory land, but that's ok. + +## the category of quivers + +Haskell quivers form a category with + +* objects are quivers + * `p :: k -> k -> Type` +* morphisms are terms of `RankNType`, + * `forall x y. p x y -> q x y` +* identity is `id` +* composition is `.` + +The standard definition of `id` and `.` work for quiver morphisms, +thanks to universal quantification. This category turns out +pretty interesting, and in many ways is analagous to Hask, the +category of Haskell `Type`s and functions. It has two interesting +monoidal products, a Cartesian product and a "composition". +And like Hask, the category of Haskell quivers has a useful hierarchy of +endofunctor typeclasses, which may be used to provide a familiar +API for the free category functor. + +Now, the free category has to a functor the category of quivers +to the category of `Category`s which is left adjoint to forgetting +the `Category` constraint. If you unpack the definition of left +adjoint in this case you find that for the free category functor `path` +you have a quiver morphism + +`qsingle :: p x y -> path p x y` + +and a function of quiver morphisms to a `Category`, + +`qfoldMap :: Category q => (forall x y. p x y -> q x y) -> path p x y -> q x y` + +such that + +`qsingle . qfoldMap f = f` + +So, you can characterize the free category abstractly using the +endofunctor hierarchy. + +## utility + +So, having broken my study of the free category into a library with +some combinators, an API and data types, I found I could re-apply +what I had learned back to Squeal migrations. It helped me clean up +and generalize that code in a nice way. I hope to see some other +uses found for free categories. diff --git a/quiver.gif b/quiver.gif new file mode 100644 index 0000000000000000000000000000000000000000..104b4cf1fe8eb47c4944092281a3e97dcb94fd46 GIT binary patch literal 1939 zcmV;E2WTY1XZC+uPgg&a3X*!NA(?si~^+^77=rl6OiR z0002Iyu27niuw5X@B9A${PDn|eRd%nv$M0)z^(lK{u(2B|Ni^Cv#X7%$9bEz&dbN1 znw#$I>RfV#`1bOvvby~G`8)ss|LeX008&_6SS>9tPa+__t)AWS`}X_&ySBD_dV0># z&;S4bA^8LW002J#EC2ui0CfS9000L6z@KnPEE41ejE#v z0Ej1J@)-{@52WfC8ug# zV!{Q47Cjya6L#aq*Z?;qEa*T%MiT_fwhH~gVu4u+7+5ICU?9l{7d}YzDBGh$h9n5$ z$&Kj(!-E?OD8R7tL4jk)=#1RFuvp>;5;q?3INXJPjGYAYe*r3`QC{Vyc3L6O1 z-wOe7;NO31Xb?a}CWMgx5lnwzaDxwcbd`dH?F3L9hG~Qlz&$${;Gsr;xDcOvddN@$ z4iyIQ!YT%2pumvQy&}SIAQ?cz3@6~ohYc(KkwJt3tbmFO5sD|l48nlO3O6eaq``06 zAbD5(*k{=|NUs8Z;0J1s&7^oh-hQSTqBmFwmeD%n*$$4}r8K2N5`M z0-t@d5ll1|4SFY@_r*T2<-^uJZOK71oPWBevSP zuBwLCFl`ek7|MaBUHl1fiug)_r7#r{vcbhEin__iAoHt;Z?{&u@R%GtN`(PFWxRzr zAlJ*P69%||oG>bUM@WD*XUYlCHD|X7%K|JsXn`V6;p7$w1f8P1L{z0f3Ou&+K$IR! zP3Fj6H*E;8N*k~%2iw}gveXnCfy2e2*>E2Tbk}Y7-FWA%_uhQt-9ZvGOMNpYfd@VK zAq5Jg^aSlRiH9{_w_QXDHi(5{Xc9=!!RDNI?)m4Shc5c)o11 z3cG6nY1;w+xzto6@c{){a`1w&2CnCJEC}7+Q zEUGk(MEpqr9txHTDo_ImVCMwD zvjPg=t?0lFdVsw($bdf&fB-ith|E;5-~l!$q#0ab7YvkyagM8IEQWc5 z7QFHcGUz~VF!_TJC_{SUJO&SPgMnshpE`E#R6E z0z}Pz#=-os7TcYU0Q$vg(meI2H1xHGBAPn zJvAK Date: Wed, 13 Nov 2019 17:20:52 -0800 Subject: [PATCH 02/19] link --- Announcement.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Announcement.md b/Announcement.md index 3015e37..aa08e15 100644 --- a/Announcement.md +++ b/Announcement.md @@ -13,9 +13,9 @@ class Category c where ``` Instances include `(->)`, the category of Haskell types and functions, -and `Kleisli`, the Kleisli category of a `Monad`. - -In Squeal, there's another instance, `Definition`, the category of +and `Kleisli`, the Kleisli category of a `Monad`. In [Squeal] +(https://github.com/morphismtech/squeal/), +there's another instance, `Definition`, the category of database schemas and DDL statements (`CREATE`, `DROP` and `ALTER`). For a while I was puzzling on how to add migration support to Squeal. From 66a0b5b295a1e444993c6809e4b5c0a74a2bfc59 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 17:22:01 -0800 Subject: [PATCH 03/19] Update Announcement.md --- Announcement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Announcement.md b/Announcement.md index aa08e15..b4dae5e 100644 --- a/Announcement.md +++ b/Announcement.md @@ -13,8 +13,8 @@ class Category c where ``` Instances include `(->)`, the category of Haskell types and functions, -and `Kleisli`, the Kleisli category of a `Monad`. In [Squeal] -(https://github.com/morphismtech/squeal/), +and `Kleisli`, the Kleisli category of a `Monad`. In +[Squeal](https://github.com/morphismtech/squeal/), there's another instance, `Definition`, the category of database schemas and DDL statements (`CREATE`, `DROP` and `ALTER`). From 0a90386634cabbcf1fef03eda9e85858b96f73e5 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 17:31:55 -0800 Subject: [PATCH 04/19] Update Announcement.md --- Announcement.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Announcement.md b/Announcement.md index b4dae5e..2642fc9 100644 --- a/Announcement.md +++ b/Announcement.md @@ -53,8 +53,8 @@ So I looked around for this datatype and I remembered a paper, written by Atze van der Ploeg and Oleg Kiselyov. They used `Path`s of `Kleisli` for efficient monadic reflection. They also introduce isomorphic datatypes to `Path`. -The paper (Kleisli Arrows of Outrageous Fortune) -[https://personal.cis.strath.ac.uk/conor.mcbride/Kleisli.pdf] +The paper +[Kleisli Arrows of Outrageous Fortune](https://personal.cis.strath.ac.uk/conor.mcbride/Kleisli.pdf) written by Conor McBride also uses `Path`, even naming it so. A couple of libraries also had it. A support library for reflection @@ -67,9 +67,6 @@ But I come from the land of category theory, and code wasn't really clarifying to me what this structure was and how it related to other similar datatypes. It turned out that in mathematics, the free category was related to something I had studied in my earlier days. -My advisor wrote a [book] -(https://www.amazon.com/Representations-Varieties-Graduate-Studies-Mathematics/dp/1470423073) -about them! ## quivers @@ -89,7 +86,11 @@ there may be multiple arrows between vertices. In math, quivers are usually studied in the context of representation theory and algebraic geometry so I was a bit shocked to see them -in programming in a very different context. +in programming in a very different context. I had seen them +when I was studying quantum algebra under my advisor Alexander Kirillov Jr. +He even wrote a +[book](https://www.amazon.com/Representations-Varieties-Graduate-Studies-Mathematics/dp/1470423073) +about quivers! A Haskell quiver is a higher kinded type, @@ -123,7 +124,7 @@ And like Hask, the category of Haskell quivers has a useful hierarchy of endofunctor typeclasses, which may be used to provide a familiar API for the free category functor. -Now, the free category has to a functor the category of quivers +Now, the free category is a functor from the category of quivers to the category of `Category`s which is left adjoint to forgetting the `Category` constraint. If you unpack the definition of left adjoint in this case you find that for the free category functor `path` From d63bf8534b0b82120530ee844be9b061e37d6831 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 17:41:23 -0800 Subject: [PATCH 05/19] Update Announcement.md --- Announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index 2642fc9..9ed04fe 100644 --- a/Announcement.md +++ b/Announcement.md @@ -138,7 +138,7 @@ and a function of quiver morphisms to a `Category`, such that -`qsingle . qfoldMap f = f` +`qfoldMap f . qsingle = f` So, you can characterize the free category abstractly using the endofunctor hierarchy. From 301cf807e3a280b3200164d9f821be620e5b411f Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 20:07:51 -0800 Subject: [PATCH 06/19] eightfold path --- Announcement.md | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/Announcement.md b/Announcement.md index 9ed04fe..6740106 100644 --- a/Announcement.md +++ b/Announcement.md @@ -104,7 +104,7 @@ instances of `Category`, `Arrow`, `Bifunctor` and `Profunctor`. Haskell quivers aren't as general as the quivers from category theory land, but that's ok. -## the category of quivers +## the eightfold path Haskell quivers form a category with @@ -124,24 +124,45 @@ And like Hask, the category of Haskell quivers has a useful hierarchy of endofunctor typeclasses, which may be used to provide a familiar API for the free category functor. -Now, the free category is a functor from the category of quivers -to the category of `Category`s which is left adjoint to forgetting +```Haskell +class QFunctor c where + qmap :: (forall x y. p x y -> q x y) -> c p x y -> c q x y +class QFunctor c => QPointed c where + qsingle :: p x y -> c p x y +class QFunctor c => QFoldable c where + qfoldMap :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y +``` + +Now, the free category is left adjoint to forgetting the `Category` constraint. If you unpack the definition of left -adjoint in this case you find that for the free category functor `path` +adjoint in this case you find that for a free category functor `c` you have a quiver morphism -`qsingle :: p x y -> path p x y` +`u :: p x y -> c p x y` and a function of quiver morphisms to a `Category`, -`qfoldMap :: Category q => (forall x y. p x y -> q x y) -> path p x y -> q x y` +`tilde :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y` such that -`qfoldMap f . qsingle = f` +`tilde f . u = f` + +But, `tilde` and `u` have the same type signatures as `qfoldMap` and `qsingle`. +So, you can characterize the free category abstractly as a constraint. + +```Haskell +{-# LANGUAGE QuantifiedConstraints #-} +class + ( QPointed c + , QFoldable c + , forall p. Category (c p) + ) => CFree c where +``` -So, you can characterize the free category abstractly using the -endofunctor hierarchy. +The free category constraint doesn't have any methods. It just has a law +which GHC can't enforce. All data structures that implement those classes +in a law abiding way are isomorphic. ## utility From 761f4aab301410e1d8ba6f4c39284654940ce714 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 20:44:19 -0800 Subject: [PATCH 07/19] Update Announcement.md --- Announcement.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Announcement.md b/Announcement.md index 6740106..17c0ace 100644 --- a/Announcement.md +++ b/Announcement.md @@ -61,7 +61,7 @@ A couple of libraries also had it. A support library for reflection without remorse [type-aligned](https://github.com/atzeus/type-aligned) existed. Also the library [free-category](https://github.com/coot/free-category) which took -those ideas a bit further. +those ideas further. But I come from the land of category theory, and code wasn't really clarifying to me what this structure was and how it related to @@ -133,22 +133,23 @@ class QFunctor c => QFoldable c where qfoldMap :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y ``` -Now, the free category is left adjoint to forgetting -the `Category` constraint. If you unpack the definition of left -adjoint in this case you find that for a free category functor `c` -you have a quiver morphism +The free category is left adjoint to "forgetting" the `Category` constraint. +If you unpack the definition of left adjoint in this case you find that for +a free category functor `c` you have a quiver morphism -`u :: p x y -> c p x y` +`i :: p x y -> c p x y` and a function of quiver morphisms to a `Category`, -`tilde :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y` +`w :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y` such that -`tilde f . u = f` +`w f . i = f` -But, `tilde` and `u` have the same type signatures as `qfoldMap` and `qsingle`. +and that these functions characterize `c` up to isomorphism as a universal property. + +But, `w` and `i` have the same type signatures as `qfoldMap` and `qsingle`. So, you can characterize the free category abstractly as a constraint. ```Haskell @@ -166,7 +167,7 @@ in a law abiding way are isomorphic. ## utility -So, having broken my study of the free category into a library with +So, I put my study of the free category into a library with some combinators, an API and data types, I found I could re-apply what I had learned back to Squeal migrations. It helped me clean up and generalize that code in a nice way. I hope to see some other From 81e267e89c4cecb906cbc213700b35e8799b8b8f Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 13 Nov 2019 21:01:04 -0800 Subject: [PATCH 08/19] u --- Announcement.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Announcement.md b/Announcement.md index 17c0ace..b5bd498 100644 --- a/Announcement.md +++ b/Announcement.md @@ -141,15 +141,15 @@ a free category functor `c` you have a quiver morphism and a function of quiver morphisms to a `Category`, -`w :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y` +`u :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y` such that -`w f . i = f` +`u f . i = f` and that these functions characterize `c` up to isomorphism as a universal property. -But, `w` and `i` have the same type signatures as `qfoldMap` and `qsingle`. +But, `u` and `i` have the same type signatures as `qfoldMap` and `qsingle`. So, you can characterize the free category abstractly as a constraint. ```Haskell From a1ffacb625b30780c3abb5fb837242c30b62374d Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Thu, 14 Nov 2019 09:50:43 -0800 Subject: [PATCH 09/19] qfst qsnd --- src/Data/Quiver.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Data/Quiver.hs b/src/Data/Quiver.hs index f903670..30bdd8b 100644 --- a/src/Data/Quiver.hs +++ b/src/Data/Quiver.hs @@ -101,8 +101,8 @@ instance Monoid m => Category (KQ m) where (https://ncatlab.org/nlab/show/cartesian+monoidal+category) of quivers.-} data ProductQ p q x y = ProductQ - { fstQ :: p x y - , sndQ :: q x y + { qfst :: p x y + , qsnd :: q x y } deriving (Eq, Ord, Show) instance (Category p, Category q, x ~ y) => Semigroup (ProductQ p q x y) where (<>) = (>>>) From 5adecb8128ff90a66cbd0b13e3455ef34c2bc541 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Thu, 14 Nov 2019 12:52:04 -0800 Subject: [PATCH 10/19] Update Announcement.md --- Announcement.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Announcement.md b/Announcement.md index b5bd498..a3f4d86 100644 --- a/Announcement.md +++ b/Announcement.md @@ -26,7 +26,7 @@ together. But, a migration system needs to track which `Definition` has been run in the past and skip it. That means you need to be able to do some processing on each `Definition` in your chain. Composing the `Definition`s smashes them together into a single `Definition`. -I needed a data structure that held a list of `Definition`s that can be +I needed a data structure that held a list of migrations that can be but are not yet composed. ``` @@ -35,7 +35,9 @@ data Path p x y where (:>>) :: p x y -> Path p y z -> Path p x z ``` -This covered my need and also conveniently solved another problem. +`Path p` is the "free category" or "path category" with steps in `p`. +`Path p` has a `Category` instance even if `p` does not. +`Path` covered my need and also conveniently solved another problem. Squeal also supported `WITH` statements, however, they had a problem. As I had typed them, I used a heterogeneous list to contain the common table expressions. This meant that each CTE had to reference From cb3494007e847d36e72df4cc8eee66eedfe1f1dc Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Thu, 14 Nov 2019 13:01:10 -0800 Subject: [PATCH 11/19] Update Announcement.md --- Announcement.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index a3f4d86..0aa280a 100644 --- a/Announcement.md +++ b/Announcement.md @@ -29,7 +29,8 @@ the `Definition`s smashes them together into a single `Definition`. I needed a data structure that held a list of migrations that can be but are not yet composed. -``` +```Haskell +{-# LANGUAGE GADTs #-} data Path p x y where Done :: Path p x x (:>>) :: p x y -> Path p y z -> Path p x z From 7b032e8287003b885bf992efcc9e4ffd57543255 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Thu, 14 Nov 2019 13:06:58 -0800 Subject: [PATCH 12/19] Update Announcement.md --- Announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index 0aa280a..07f30b3 100644 --- a/Announcement.md +++ b/Announcement.md @@ -118,7 +118,7 @@ Haskell quivers form a category with * identity is `id` * composition is `.` -The standard definition of `id` and `.` work for quiver morphisms, +`Prelude`s `id` and `.` work for quiver morphisms, thanks to universal quantification. This category turns out pretty interesting, and in many ways is analagous to Hask, the category of Haskell `Type`s and functions. It has two interesting From 7755f5791b07230db40a29fde25a637fcb1ff628 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Fri, 15 Nov 2019 07:57:15 -0800 Subject: [PATCH 13/19] Update Announcement.md --- Announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index 07f30b3..925e058 100644 --- a/Announcement.md +++ b/Announcement.md @@ -118,7 +118,7 @@ Haskell quivers form a category with * identity is `id` * composition is `.` -`Prelude`s `id` and `.` work for quiver morphisms, +`Prelude`'s `id` and `.` work for quiver morphisms, thanks to universal quantification. This category turns out pretty interesting, and in many ways is analagous to Hask, the category of Haskell `Type`s and functions. It has two interesting From f4938bd4982014bf7505ea76b3c0312745932fbc Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Fri, 15 Nov 2019 08:12:58 -0800 Subject: [PATCH 14/19] Update Announcement.md --- Announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index 925e058..5e0ed34 100644 --- a/Announcement.md +++ b/Announcement.md @@ -13,7 +13,7 @@ class Category c where ``` Instances include `(->)`, the category of Haskell types and functions, -and `Kleisli`, the Kleisli category of a `Monad`. In +and `Kleisli m`, the Kleisli category of a `Monad`. In [Squeal](https://github.com/morphismtech/squeal/), there's another instance, `Definition`, the category of database schemas and DDL statements (`CREATE`, `DROP` and `ALTER`). From 9ea2dbe908e778c325884be7808903704410d574 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Fri, 15 Nov 2019 09:39:52 -0800 Subject: [PATCH 15/19] Update Announcement.md --- Announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Announcement.md b/Announcement.md index 5e0ed34..e1bc492 100644 --- a/Announcement.md +++ b/Announcement.md @@ -24,7 +24,7 @@ As a first pass, you can say your migration system is just `Definition`s with the `Category` instance allowing you to chain your migrations together. But, a migration system needs to track which `Definition` has been run in the past and skip it. That means you need to be able -to do some processing on each `Definition` in your chain. Composing +to do some processing on each migration in your chain. Composing the `Definition`s smashes them together into a single `Definition`. I needed a data structure that held a list of migrations that can be but are not yet composed. From 42d0eded5b5146367247e76c49437a1a79fc18e0 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Fri, 15 Nov 2019 09:47:02 -0800 Subject: [PATCH 16/19] Update Announcement.md --- Announcement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Announcement.md b/Announcement.md index e1bc492..14e43c5 100644 --- a/Announcement.md +++ b/Announcement.md @@ -22,8 +22,8 @@ For a while I was puzzling on how to add migration support to Squeal. Support for DDL gets you a long way, but not the whole way. As a first pass, you can say your migration system is just `Definition`s with the `Category` instance allowing you to chain your migrations -together. But, a migration system needs to track which `Definition` has -been run in the past and skip it. That means you need to be able +together. But, a migration system needs to track which migrations have +been run in the past and safely skip them. That means you need to be able to do some processing on each migration in your chain. Composing the `Definition`s smashes them together into a single `Definition`. I needed a data structure that held a list of migrations that can be From 08d3f5a48f7431639c4fd421fa4c5f4101790cbd Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Mon, 18 Nov 2019 10:25:20 -0800 Subject: [PATCH 17/19] Update Announcement.md --- Announcement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Announcement.md b/Announcement.md index 14e43c5..bf79856 100644 --- a/Announcement.md +++ b/Announcement.md @@ -62,8 +62,8 @@ written by Conor McBride also uses `Path`, even naming it so. A couple of libraries also had it. A support library for reflection without remorse [type-aligned](https://github.com/atzeus/type-aligned) -existed. Also the library -[free-category](https://github.com/coot/free-category) which took +existed. Also the remarkably fascinating and general library +[free-category](https://github.com/coot/free-category) took those ideas further. But I come from the land of category theory, and code wasn't really From ccaf12eaeb71928ff3e53f53d7e0de69f7b1a9b3 Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 12 Feb 2020 22:39:19 -0800 Subject: [PATCH 18/19] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 505cb91..9166e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Revision history for free-categories +## 0.2.0.0 -- 2020-02-12 + +* Separate into 3 modules. +* Refactor typeclasses. +* Rename functions + ## 0.1.0.0 -- 2019-10-01 * First version. From ddfc1869cad0de2f54e14748a9c2b5c2afb6613e Mon Sep 17 00:00:00 2001 From: Eitan Chatav Date: Wed, 12 Feb 2020 22:48:09 -0800 Subject: [PATCH 19/19] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ae38c13..2edec02 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ The free category on a quiver. + +![quiver](quiver.gif)