{"id":468,"date":"2016-12-22T13:33:52","date_gmt":"2016-12-22T13:33:52","guid":{"rendered":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/?p=468"},"modified":"2017-11-16T10:59:23","modified_gmt":"2017-11-16T10:59:23","slug":"graphs-in-disguise","status":"publish","type":"post","link":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/graphs-in-disguise\/","title":{"rendered":"Graphs in disguise: from todo lists to build systems"},"content":{"rendered":"<p>In this blog post we will look at an example of\u00a0using <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/an-algebra-of-graphs\/\">the algebra of graphs<\/a> for manipulating <em>sequences<\/em> of items, which at first sight might not look like graphs, but are actually <em>dependency graphs<\/em> in disguise. We will develop a\u00a0tiny DSL\u00a0for composing\u00a0todo lists on top of the <a href=\"https:\/\/github.com\/snowleopard\/alga\">alga library<\/a> and will\u00a0show how it can be used for planning a holiday and, on a more serious note, for writing software build systems. This blog post will partially answer\u00a0the question about possible applications of the algebra of graphs that was asked in <a href=\"https:\/\/www.reddit.com\/r\/haskell\/comments\/5gzpqb\/an_algebra_of_graphs\/\">this reddit discussion<\/a>.<\/p>\n<p><strong>Update:<\/strong>\u00a0This series of blog posts was published as a <a href=\"https:\/\/github.com\/snowleopard\/alga-paper\">functional pearl<\/a> at the Haskell Symposium 2017.<\/p>\n<p><!--more--><\/p>\n<h4>Todo lists and the algebra of graphs<\/h4>\n<p><em>Todo lists<\/em> are sequences of <em>items<\/em> that, as one would expect, need to be done. The order of items in the sequence matters, because some items may depend on others. The simplest todo list is the <em>empty<\/em> one. Then we have todo lists containing a single item, from which we can build up longer lists\u00a0using the same operators we introduced\u00a0to construct graphs.<\/p>\n<p>An item will correspond to a graph vertex. We&#8217;ll use the\u00a0<strong><code>OverloadedStrings<\/code><\/strong> GHC extension, so we can create\u00a0todo items without explicitly wrapping them into a\u00a0<strong><code>vertex<\/code><\/strong>.\u00a0This will also allow everyone to choose their favourite representation for strings; plain old <strong><code>String<\/code><\/strong>\u00a0is fine for our examples:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\">{-# <span style=\"color: #794938\">LANGUAGE<\/span> OverloadedStrings #-}\r\n<span style=\"color: #794938\">import<\/span> <span style=\"color: #691c97\">Data.String<\/span>\r\n\r\n<span style=\"color: #794938\">import<\/span> <span style=\"color: #691c97\">Algebra.Graph<\/span>\r\n<span style=\"color: #794938\">import<\/span> <span style=\"color: #691c97\">Algebra.Graph.Util<\/span>\r\n\r\n<span style=\"color: #794938\">instance<\/span> (<span style=\"color: #a71d5d;font-style: italic\">IsString<\/span> <span style=\"color: #234a97\">a<\/span>, <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">IsString<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    fromString <span style=\"color: #794938\">=<\/span> vertex <span style=\"color: #794938\">.<\/span> fromString\r\n\r\n<span style=\"color: #bf4f24\">shopping<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nshopping <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span>\r\n<\/pre>\n<p>Here <strong><code>Todo<\/code><\/strong> is a <strong><code>Graph<\/code><\/strong> instance whose implementation\u00a0will be revealed later. One can combine several items\u00a0into a single todo list using the <em>overlay<\/em> operator + of the algebra:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">shopping<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nshopping <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span>\r\n<\/pre>\n<p>The <em>semantics<\/em>\u00a0of a todo list is just a list of items in the order they can be completed, or <strong><code>Nothing<\/code><\/strong> if the there is no possible completion order that satisfies all dependency constraints between different items. We can extract the semantics using\u00a0<strong><code>todo<\/code><\/strong> function with the following signature:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">todo<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #691c97\">Maybe<\/span> [<span style=\"color: #234a97\">a<\/span>]\r\n<\/pre>\n<p>The overlay operator is commutative, therefore reordering items in the shopping list does not change the semantics:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> todo shopping\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo <span style=\"color: #794938\">$<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span>\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> shopping <span style=\"color: #794938\">==<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span>\r\n<span style=\"color: #b4371f\">True<\/span>\r\n<\/pre>\n<p>As you can see, the items are simply ordered alphabetically as there are no dependencies between them. Let&#8217;s add some! To do that we&#8217;ll use the <em>connect<\/em> operator \u2192\u00a0from the algebra. When two todo lists are combined with\u00a0\u2192, the meaning is that all items in the first list must be completed before we can start completing items from the second todo list. I&#8217;m currently planning a holiday trip to visit friends and therefore will need to pack all stuff that I buy before travelling:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">holiday<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nholiday <span style=\"color: #794938\">=<\/span> shopping * <span style=\"color: #0b6125\">\"pack\"<\/span> * <span style=\"color: #0b6125\">\"travel\"<\/span>\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo holiday\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"pack\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"travel\"<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> shopping <span style=\"color: #794938\">==<\/span> holiday\r\n<span style=\"color: #b4371f\">False<\/span>\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> shopping <span style=\"color: #794938\">`isSubgraphOf`<\/span> holiday\r\n<span style=\"color: #b4371f\">True<\/span>\r\n<\/pre>\n<p>Items <strong><code>\"pack\"<\/code><\/strong> and <strong><code>\"travel\"<\/code><\/strong> have been appended\u00a0to the end of the list even though <strong><code>\"pack\"<\/code><\/strong> comes before <strong><code>\"presents\"<\/code><\/strong> alphabetically, and rightly so: we can&#8217;t pack presents before we buy them!<\/p>\n<p>Now let&#8217;s\u00a0add a new dependency constraint to an existing todo list. For example, I might\u00a0want to buy a new scarf before a coat, because I would like to make sure\u00a0the coat looks good\u00a0with the new scarf:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> todo <span style=\"color: #794938\">$<\/span> holiday <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span> * <span style=\"color: #0b6125\">\"coat\"<\/span>\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"pack\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"travel\"<\/span>]\r\n<\/pre>\n<p>Look how the resulting list\u00a0changed:\u00a0<strong><code>\"coat\"<\/code><\/strong> has been moved after\u00a0<strong><code>\"scarf\"<\/code><\/strong> to meet the new constraint! Of course, it&#8217;s not too difficult to add contradictory\u00a0constraints, making the todo list impossible to schedule:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> todo <span style=\"color: #794938\">$<\/span> holiday <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"travel\"<\/span> * <span style=\"color: #0b6125\">\"presents\"<\/span>\r\n<span style=\"color: #b4371f\">Nothing<\/span>\r\n<\/pre>\n<p>There is nothing we can do to complete all items if there is\u00a0a circular dependency in our todo list: <strong><code>\"presents\"<\/code><\/strong>\u00a0\u2192 <strong><code>\"pack\"<\/code><\/strong> \u2192\u00a0<strong><code>\"travel\"<\/code><\/strong>\u00a0\u2192\u00a0<strong><code>\"presents\"<\/code><\/strong>.<\/p>\n<p>It may sometimes be useful to have some notion of <em>item priorities<\/em>\u00a0to schedule some items\u00a0as soon or as late as possible.\u00a0Let me illustrate this with an example, by modifying our todo lists as follows:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">shopping<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nshopping <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"phone wife\"<\/span> * <span style=\"color: #0b6125\">\"scarf\"<\/span>\r\n\r\n<span style=\"color: #bf4f24\">holiday<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nholiday <span style=\"color: #794938\">=<\/span> shopping * <span style=\"color: #0b6125\">\"pack\"<\/span> * <span style=\"color: #0b6125\">\"travel\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span> * <span style=\"color: #0b6125\">\"coat\"<\/span>\r\n<\/pre>\n<p>As you see, I now would like to phone my wife before buying the scarf to make sure it also matches the colour of one of her scarves (she has a dozen of them and I can&#8217;t possibly remember all the colours). Let&#8217;s see how this changes the resulting order:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> todo holiday\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"phone wife\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"pack\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"travel\"<\/span>]\r\n<\/pre>\n<p>This works but is a little unsatisfactory:\u00a0ideally I&#8217;d like to phone my wife <em>right before<\/em> buying the scarf. To achieve that I\u00a0can amend\u00a0the\u00a0shopping list by changing\u00a0the priority of the item <strong><code>\"phone wife\"<\/code><\/strong>:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #5a525f;font-style: italic\">-- Lower the priority of items in a given todo list<\/span>\r\n<span style=\"color: #bf4f24\">low<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #234a97\">a<\/span>\r\n\r\n<span style=\"color: #bf4f24\">shopping<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nshopping <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> low <span style=\"color: #0b6125\">\"phone wife\"<\/span> * <span style=\"color: #0b6125\">\"scarf\"<\/span>\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo holiday\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"presents\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"phone wife\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"scarf\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"coat\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"pack\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"travel\"<\/span>]\r\n<\/pre>\n<p>Aha, this is better: <strong><code>\"phone wife\"<\/code><\/strong>\u00a0got\u00a0scheduled as late as possible,\u00a0and is now right next to <strong><code>\"scarf\"<\/code><\/strong>, as desired. But wait &#8212; if my wife finds out that I gave a low priority to my phone calls to her, I&#8217;ll get into trouble! I need to find a better way to achieve the same effect. In essence, we would like to have a variant of the connect operator that pulls the arguments\u00a0together as close as possible during scheduling (and, alternatively, we may also want to repel arguments as far from each other as possible).<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #5a525f;font-style: italic\">-- Pull the arguments together as close as possible<\/span>\r\n(<span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span>) <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Ord<\/span> a <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a\r\n\r\n<span style=\"color: #5a525f;font-style: italic\">-- Repel the arguments as far as possible<\/span>\r\n(<span style=\"color: #794938\">&gt;<\/span>*<span style=\"color: #794938\">&lt;<\/span>) <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Ord<\/span> a <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">Todo<\/span> a\r\n\r\n<span style=\"color: #bf4f24\">shopping<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\nshopping <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"presents\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"coat\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"phone wife\"<\/span> <span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span> <span style=\"color: #0b6125\">\"scarf\"<\/span>\r\n<\/pre>\n<p>This looks better and leads to the same result as the code above.<\/p>\n<p>The final\u00a0<strong><code>holiday<\/code><\/strong> expression can be visualised as follows:<br \/>\n<a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/files\/2016\/12\/holiday-expression.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-205\" src=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/files\/2016\/12\/holiday-expression.png\" alt=\"Graph expression\" width=\"2400\" height=\"988\" \/><\/a><\/p>\n<p>Here the overlay operator + is shown simply by placing its arguments next to each other, the connect operators are shown by arrows, and the arrow with a small triangle stands for the <em>tightly connect<\/em> operator <strong><code>~*~<\/code><\/strong>. By following the laws of the algebra, we can flatten the graph expression into a dependency graph shown below:<br \/>\n<a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/files\/2016\/12\/holiday-dependency-graph.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-205\" src=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/files\/2016\/12\/holiday-dependency-graph.png\" alt=\"Dependency graph\" width=\"2400\" height=\"988\" \/><\/a><\/p>\n<p>The graph is then <em>linearised<\/em> into a list\u00a0of items by the\u00a0<strong><code>todo<\/code><\/strong> function.<\/p>\n<p>So, here you go: you can plan your holiday (or anything else) in Haskell using <a href=\"https:\/\/github.com\/snowleopard\/alga\">the alga library<\/a>!<\/p>\n<h4>Constructing command lines in build systems<\/h4>\n<p>The above reminds me of <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/cloud-and-dynamic-builds\/\">build systems<\/a> that construct command lines for executing various external programs, such as compilers, linkers, etc. A command line is just a list\u00a0of strings, that typically include the path to the program that is being executed, paths to source files, and various configuration flags. Some of these strings may have order constraints between them, quite\u00a0similar to todo lists. Let&#8217;s see if we can\u00a0use\u00a0<a href=\"https:\/\/github.com\/snowleopard\/alga\/blob\/master\/src\/Algebra\/Graph\/Todo.hs\">our tiny DSL for\u00a0todo lists<\/a> for describing command lines.<\/p>\n<p>Here is a simple command line to compile <strong><code>\"src.c\"<\/code><\/strong> with GCC compiler:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">cmdLine1<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\ncmdLine1 <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"gcc\"<\/span> * (<span style=\"color: #0b6125\">\"-c\"<\/span> <span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span> <span style=\"color: #0b6125\">\"src.c\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"-o\"<\/span> <span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span> <span style=\"color: #0b6125\">\"src.o\"<\/span>)\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo cmdLine1\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"gcc\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-o\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.o\"<\/span>]\r\n<\/pre>\n<p>Build systems are regularly\u00a0refactored, and it is useful\u00a0to track changes in a build system to automatically rebuild affected files if need be (for example, in the new GHC build system <a href=\"https:\/\/github.com\/snowleopard\/hadrian\">Hadrian<\/a> we track changes in command lines and this helps a lot in its development).\u00a0Some changes do not\u00a0change the semantics of a build system and can therefore be safely ignored. As an example, one can rewrite <strong><code>cmdLine1<\/code><\/strong> defined above by swapping the source and object file parts of the command line:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">cmdLine2<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\ncmdLine2 <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"gcc\"<\/span> * (<span style=\"color: #0b6125\">\"-o\"<\/span> <span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span> <span style=\"color: #0b6125\">\"src.o\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"-c\"<\/span> <span style=\"color: #794938\">~<\/span>*<span style=\"color: #794938\">~<\/span> <span style=\"color: #0b6125\">\"src.c\"<\/span>)\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> cmdLine1 <span style=\"color: #794938\">==<\/span> cmdLine2\r\n<span style=\"color: #b4371f\">True<\/span>\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo cmdLine2\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"gcc\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-o\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.o\"<\/span>]\r\n<\/pre>\n<p>As you can see, the above change has no effect, as we\u00a0would expect from the commutativity of +. Replacing\u00a0<strong><code>~*~<\/code><\/strong>\u00a0with the usual connect operator on the other hand sometimes leads to changes in the semantics:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">cmdLine3<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\ncmdLine3 <span style=\"color: #794938\">=<\/span> <span style=\"color: #0b6125\">\"gcc\"<\/span> * (<span style=\"color: #0b6125\">\"-c\"<\/span> * <span style=\"color: #0b6125\">\"src.c\"<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #0b6125\">\"-o\"<\/span> * <span style=\"color: #0b6125\">\"src.o\"<\/span>)\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> cmdLine1 <span style=\"color: #794938\">==<\/span> cmdLine3\r\n<span style=\"color: #b4371f\">False<\/span>\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo cmdLine3\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"gcc\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-o\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.o\"<\/span>]\r\n<\/pre>\n<p>The resulting\u00a0sequence is correct from the point of view of a dependency graph, but is not a valid command line: the flag pairs got pushed apart. The change in semantics is recognised by the algebra and a rerun of the build system should reveal the error.<\/p>\n<p>As a final exercise, let&#8217;s write\u00a0a\u00a0function that transforms command lines:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">optimise<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #691c97\">Int<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Todo<\/span> <span style=\"color: #691c97\">String<\/span>\r\noptimise level <span style=\"color: #794938\">=<\/span> (* flag)\r\n  <span style=\"color: #794938\">where<\/span>\r\n    flag <span style=\"color: #794938\">=<\/span> vertex <span style=\"color: #794938\">$<\/span> <span style=\"color: #0b6125\">\"-O\"<\/span> <span style=\"color: #794938\">++<\/span> <span style=\"color: #693a17\">show<\/span> level\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> todo <span style=\"color: #794938\">$<\/span> optimise <span style=\"color: #811f24;font-weight: bold\">2<\/span> cmdLine1\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #0b6125\">\"gcc\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.c\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-o\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"src.o\"<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #0b6125\">\"-O2\"<\/span>]\r\n<\/pre>\n<p>As you can see, <strong><code>optimise 2<\/code><\/strong>\u00a0appends the optimisation flag <strong><code>\"-O2\"<\/code><\/strong> at the end of the command line, i.e. <strong><code>optimise 2 ==\u00a0(* \"-O2\")<\/code><\/strong>.<\/p>\n<p>Command lines in real build systems contain many\u00a0<em>conditional<\/em> flags that are\u00a0included only when compiling certain files on certain platforms, etc. You can read about\u00a0how we deal with conditional flags in Hadrian <a href=\"https:\/\/www.staff.ncl.ac.uk\/andrey.mokhov\/Hadrian.pdf\">here<\/a>.<\/p>\n<h4>Under the hood<\/h4>\n<p>Scheduling a list of items subject to dependency constraints is a\u00a0well-known problem, which is solved by <a href=\"https:\/\/en.wikipedia.org\/wiki\/Topological_sorting\"><em>topological sort<\/em><\/a>\u00a0of the underlying dependency graph.\u00a0GHC&#8217;s <strong><code>containers<\/code><\/strong> library has an implementation of topological sort in\u00a0<strong><code>Data.Graph<\/code><\/strong> module. It operates on adjacency lists and to reuse it we can define the following <strong><code>Graph<\/code><\/strong> instance:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">newtype<\/span> <span style=\"color: #811f24;font-weight: bold\">AdjacencyMap<\/span> a <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">AM<\/span> { adjacencyMap <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span> a (<span style=\"color: #811f24;font-weight: bold\">Set<\/span> a) }\r\n    <span style=\"color: #794938\">deriving<\/span> (<span style=\"color: #bf4f24\">Eq<\/span>, <span style=\"color: #bf4f24\">Show<\/span>)\r\n\r\n<span style=\"color: #794938\">instance<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> (<span style=\"color: #a71d5d;font-style: italic\">AdjacencyMap<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    <span style=\"color: #794938\">type<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span> (<span style=\"color: #811f24;font-weight: bold\">AdjacencyMap<\/span> a) <span style=\"color: #794938\">=<\/span> a\r\n    empty       <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">AM<\/span> <span style=\"color: #794938\">$<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span><span style=\"color: #794938\">.<\/span>empty\r\n    vertex  x   <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">AM<\/span> <span style=\"color: #794938\">$<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span><span style=\"color: #794938\">.<\/span>singleton x <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>empty\r\n    overlay x y <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">AM<\/span> <span style=\"color: #794938\">$<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span><span style=\"color: #794938\">.<\/span>unionWith <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union\r\n        (adjacencyMap x) (adjacencyMap y)\r\n    connect x y <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">AM<\/span> <span style=\"color: #794938\">$<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span><span style=\"color: #794938\">.<\/span>unionsWith <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union\r\n        [ adjacencyMap x<span style=\"color: #794938\">,<\/span> adjacencyMap y\r\n        <span style=\"color: #794938\">,<\/span> fromSet (<span style=\"color: #693a17\">const<\/span> <span style=\"color: #794938\">.<\/span> keysSet <span style=\"color: #794938\">$<\/span> adjacencyMap y)\r\n                  (keysSet <span style=\"color: #794938\">$<\/span> adjacencyMap x) ]\r\n\r\n<span style=\"color: #bf4f24\">adjacencyList<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">AdjacencyMap<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">-&gt;<\/span> [(<span style=\"color: #234a97\">a<\/span>, [<span style=\"color: #234a97\">a<\/span>])]\r\nadjacencyList <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">map<\/span> (<span style=\"color: #693a17\">fmap<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>toAscList) <span style=\"color: #794938\">.<\/span> <span style=\"color: #811f24;font-weight: bold\">Map<\/span><span style=\"color: #794938\">.<\/span>toAscList <span style=\"color: #794938\">.<\/span> adjacencyMap\r\n\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> adjacencyList <span style=\"color: #794938\">$<\/span> clique [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n[(<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span>[<span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>])<span style=\"color: #794938\">,<\/span>(<span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span>[<span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>])<span style=\"color: #794938\">,<\/span>(<span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span>[<span style=\"color: #811f24;font-weight: bold\">4<\/span>])<span style=\"color: #794938\">,<\/span>(<span style=\"color: #811f24;font-weight: bold\">4<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">[]<\/span>)]\r\n<\/pre>\n<p><strong><code>Todo<\/code><\/strong> is built on top of the <strong><code>TopSort<\/code><\/strong> graph instance, which is just a\u00a0newtype wrapper around <strong><code>AdjacencyMap<\/code><\/strong> based representation of graphs:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">newtype<\/span> <span style=\"color: #811f24;font-weight: bold\">TopSort<\/span> a <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">TS<\/span> { fromTopSort <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">AdjacencyMap<\/span> a }\r\n    <span style=\"color: #794938\">deriving<\/span> (<span style=\"color: #bf4f24\">Show<\/span>, <span style=\"color: #bf4f24\">Num<\/span>)\r\n\r\n<span style=\"color: #794938\">instance<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Eq<\/span> (<span style=\"color: #a71d5d;font-style: italic\">TopSort<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    x <span style=\"color: #794938\">==<\/span> y <span style=\"color: #794938\">=<\/span> topSort x <span style=\"color: #794938\">==<\/span> topSort y\r\n<\/pre>\n<p>The custom <strong><code>Eq<\/code><\/strong> instance makes sure that graphs are considered equal if their topological sorts coincide. In particular all cyclic graphs fall into the same equivalence class corresponding to<code> <\/code><strong><code>topSort g == Nothing<\/code><\/strong>:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> path [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>] <span style=\"color: #794938\">==<\/span> (clique [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>] <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">TopSort<\/span> <span style=\"color: #811f24;font-weight: bold\">Int<\/span>)\r\n<span style=\"color: #b4371f\">True<\/span>\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> topSort <span style=\"color: #794938\">$<\/span> clique [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> topSort <span style=\"color: #794938\">$<\/span> path [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> topSort <span style=\"color: #794938\">$<\/span> transpose <span style=\"color: #794938\">$<\/span> clique [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #b4371f\">Just<\/span> [<span style=\"color: #811f24;font-weight: bold\">4<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">1<\/span>]\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> topSort <span style=\"color: #794938\">$<\/span> circuit [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">4<\/span>]\r\n<span style=\"color: #b4371f\">Nothing<\/span>\r\n<\/pre>\n<p>Function <strong><code>topSort<\/code><\/strong>\u00a0simply calls <strong><code>Data.Graph.topSort<\/code><\/strong> performing\u00a0the necessary plumbing, which is not particularly interesting.<\/p>\n<p>The\u00a0current implementation has <a href=\"https:\/\/github.com\/snowleopard\/alga\/issues\/2\">two issues<\/a>: the topological sort is not always lexicographically first, as evidenced by <strong><code>cmdLine3<\/code><\/strong> above, where <strong><code>\"-o\"<\/code><\/strong> precedes <strong><code>\"-c\"<\/code><\/strong> in the final ordering. The second issue is that\u00a0<strong><code>topSort<\/code><\/strong> does not satisfy\u00a0the <em>closure axiom<\/em> defined in <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/graphs-a-la-carte\/\">the previous blog post<\/a>.\u00a0One possible approach\u00a0to fix this is to compute the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Transitive_reduction\"><em>transitive reduction<\/em><\/a> of the underlying dependency graph before the topological sort.<\/p>\n<p>Have a great holiday everyone!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post we will look at an example of\u00a0using the algebra of graphs for manipulating sequences of items, which at first sight might not look like graphs, but are actually dependency graphs in disguise. We will develop a\u00a0tiny DSL\u00a0for composing\u00a0todo lists on top of the alga library and will\u00a0show how it can be &hellip; <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/graphs-in-disguise\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Graphs in disguise: from todo lists to build systems<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1174,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,10],"tags":[13,4],"class_list":["post-468","post","type-post","status-publish","format-standard","hentry","category-coding","category-math","tag-algebra","tag-haskell"],"_links":{"self":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/468","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/users\/1174"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/comments?post=468"}],"version-history":[{"count":30,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/468\/revisions"}],"predecessor-version":[{"id":623,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/468\/revisions\/623"}],"wp:attachment":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/media?parent=468"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/categories?post=468"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/tags?post=468"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}