<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>The Comonad.Reader</title><link>https://comonad.com/reader/</link><description>Writing, talks, live coding, and papers: types, (co)monads, substructural logic</description><item><title>Live Coding — Session 26</title><link>https://comonad.com/reader/talks/live-coding-26/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-26/</guid><pubDate>Sat, 13 May 2023 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 13 May 2023 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Pe8LPUK787c&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Pe8LPUK787c&quot;&gt;Watch on YouTube&lt;/a&gt; · 85 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Getting back in the saddle after 4 years away. Dusting off my work on hkd-based distributive functors.   -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-26/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Internalized Guarded Recursion for Equational Reasoning</title><link>https://comonad.com/reader/2022/internalized-guarded-recursion-for-equational-reasoning/</link><guid isPermaLink="false">https://comonad.com/reader/2022/internalized-guarded-recursion-for-equational-reasoning/</guid><pubDate>Fri, 21 Oct 2022 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 21 October 2022&lt;/p&gt;&lt;p&gt;I recently &lt;a href=&quot;https://www.youtube.com/watch?v=xdUgkGqKjS8&quot;&gt;presented a paper&lt;/a&gt; on infinite traversals at the Haskell Symposium: &lt;a href=&quot;https://gbaz.github.io/papers/3546189.3549915.pdf&quot;&gt;A totally predictable outcome: an investigation of traversals of infinite structures&lt;/a&gt;. The main result there is a characterization of when a call to &lt;code&gt;traverse&lt;/code&gt; on an infinite Traversable functor (like an infinite lazy list) yields a non-bottom result. It turns out this is a condition on the Applicative one traverses with that loosely amounts to it having only a single data constructor. What I want to talk about here is how the technique introduced in that paper, which I call &quot;internal guarded recursion&quot; can be used not only in a lightweight formal way to prove characterization theorems or the like, but just in everyday programming as a &quot;back of the envelope&quot; or &quot;streetfighting&quot; hack to quickly figure out when recursive functional programs terminate and when they go into infinite loops.&lt;/p&gt;
&lt;p&gt;Let's talk about the basic trick that makes the whole thing work. First, we introduce an abstract newtype for identity, which we will disallow pattern matching against, and instead only allow access to through the structure of an applicative functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure = &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; f &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; (f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we introduce the &lt;em&gt;only&lt;/em&gt; function allowed to perform recursion:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lfix&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; a -&amp;gt; a) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lfix&lt;/span&gt; f = fix (f . pure)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This function has almost the same type signature as the typical fixpoint operator, but it &quot;guards&quot; the argument to the function it is taking the fixedpoint of by our abstract &lt;code&gt;Later&lt;/code&gt; type constructor.&lt;/p&gt;
&lt;p&gt;Now, if you write code that only has recursion via `lfix` and no other function can implicitly or explicitly invoke itself (which the paper refers to as &quot;working in the guarded fragment), your code will &lt;em&gt;never produce a bottom&lt;/em&gt;. You can have whatever sorts of recursive Haskell '98 data definitions you like, it doesn't matter! (However, if you have &quot;impredicative&quot; datatypes that pack polymorphic functions into them, I think it would matter... but let's leave that aside). Try, for example, using only this form of recursion, to write a function that produces an infinite list. You'll realize that each recursive step requires using up one &lt;code&gt;Later&lt;/code&gt; constructor as &quot;fuel&quot;. And since there's no way to get an infinite amount of &lt;code&gt;Later&lt;/code&gt; constructors to begin with, you'll only be able to produce lists of finite depth.&lt;/p&gt;
&lt;p&gt;However, we &lt;em&gt;can&lt;/em&gt; create related data structures to our existing ones, which &quot;guard&quot; their own recurrence behind a &lt;code&gt;Later&lt;/code&gt; type constructor as well -- and we can create, consume and manipulate those also, and also do so without risk of writing an expression that produces a bottom. For example, here is the type of possibly infinite lists:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a =&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
    | &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here is a function that interleaves two such lists:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;sinterleave&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;sinterleave&lt;/span&gt; = lfix $ \f s1 s2 -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s1 &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x xs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x (f &amp;lt; *&amp;gt; pure s2 &amp;lt; *&amp;gt; xs)
    _ -&amp;gt; s2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I'm going to diverge from the paper and pose a sort of general problem, based on some discussions I had at ICFP. Suppose you have some tricky recursion, possibly involving &quot;&lt;a href=&quot;https://wiki.haskell.org/Tying_the_Knot&quot;&gt;tying the knot&lt;/a&gt;&quot; and want to show that it terminates, or to figure out under which conditions it terminates -- how can you do that? It turns out that internal guarded recursion can help! Here's the recipe:&lt;/p&gt;
&lt;p&gt;1. Write your function using only explicit recursion (via &lt;code&gt;fix&lt;/code&gt;).&lt;br&gt;
2. Change &lt;code&gt;fix&lt;/code&gt; to &lt;code&gt;lfix&lt;/code&gt;&lt;br&gt;
3. Figure out what work you have to do adding applicative operations involving &lt;code&gt;Later&lt;/code&gt; to fix the types.&lt;/p&gt;
&lt;p&gt;The paper has in it a general theorem that says, loosely speaking, that if you have code involving &lt;code&gt;lfix&lt;/code&gt; and &lt;code&gt;Later&lt;/code&gt;, and change that back to &lt;code&gt;fix&lt;/code&gt; and erase all the mucking around with &lt;code&gt;Later&lt;/code&gt; you get &quot;essentially the same&quot; function, and you still have a guarantee it won't produce bottoms. So this just turns that around -- start with your normal code, and show you can write it even in the guarded fragment, and then that tells you the properties of your original code!&lt;/p&gt;
&lt;p&gt;I'll present this approach to reasoning about two tricky but well known problems in functional programming. First, as suggested by Tom Schrijvers as a question at the talk, is the famous &quot;repmin&quot; function introduced by Bird in &lt;a href=&quot;https://link.springer.com/article/10.1007/BF00264249&quot;&gt;1984&lt;/a&gt;. This is a program that makes essential use of laziness to traverse a tree only once, but replacing each element in the tree by the minimum element anywhere in the tree. Here's a quick one-liner version, making use of traversal in the writer monad -- it works over any finite traversable structure, including typical trees. But it is perhaps easiest to test it over lists. For now, we'll ignore the issue of what happens with traversals of infinite structures, as that will complicate the example.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;repMin1&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a) =&amp;gt; t a -&amp;gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;repMin1&lt;/span&gt; xs =
     &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; (ans,m) = fmap minimum . runWriter $
                    traverse (\x -&amp;gt; tell [x] &amp;gt;&amp;gt; pure m) xs &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; ans
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that this above definition makes use of a recursive definition -- the body of the definition of &lt;code&gt;(ans,m)&lt;/code&gt; makes use of the &lt;code&gt;m&lt;/code&gt; being defined. This works because the definition does not pattern match on the m to compute -- otherwise we would bottom out. Using internal guarded recursion, we can let the type system guide us into rewriting our code into a form where it is directly evident that this does not bottom, rather than relying on careful reasoning about semantics. The first step is to mechanically transform the initial definition into one that is exactly the same, but where the implicit recursion has been rendered explicit by use of fix:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;repMin2&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a) =&amp;gt; t a -&amp;gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;repMin2&lt;/span&gt; xs =
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; res = fix go &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; fst res
   &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go res = fmap minimum . runWriter $
               traverse (\x -&amp;gt; tell [x] &amp;gt;&amp;gt; pure (snd res)) xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next step is to now replace &lt;code&gt;fix&lt;/code&gt; by &lt;code&gt;lfix&lt;/code&gt;. When we do so, the type of &lt;code&gt;go&lt;/code&gt; will no longer be correct. In particular, its argument, &lt;code&gt;res&lt;/code&gt; will now be guarded by a &lt;code&gt;Later&lt;/code&gt;. So we can no longer apply &lt;code&gt;snd&lt;/code&gt; directly to it, but instead have to &lt;code&gt;fmap&lt;/code&gt;. The compiler will notice this and yell at us, at which point we make that small tweak as well. In turn, this forces a change to the type signature of the overall function. With that done, everything still checks!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;repMin3&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a) =&amp;gt; t a -&amp;gt; t (&lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;repMin3&lt;/span&gt; xs =
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; res = lfix go &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; fst res
   &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go res = fmap minimum . runWriter $
                traverse (\x -&amp;gt; tell [x] &amp;gt;&amp;gt; pure (snd &amp;lt; $&amp;gt; res)) xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have now verified that the original &lt;code&gt;repMin1&lt;/code&gt; function does not bottom out on finite structures. Further, the &quot;one layer&quot; of &lt;code&gt;Later&lt;/code&gt; in the type of &lt;code&gt;repMin3&lt;/code&gt; tells us that there was exactly one recursive step invoked in computing the final result!&lt;/p&gt;
&lt;p&gt;The astute reader may have noticed a further complication -- to genuinely be in the guarded recursive fragment, we need to make sure all functions in sight have not been written using standard recursion, but only with guarded recursion. But in fact, both &lt;code&gt;minimum&lt;/code&gt; and &lt;code&gt;traverse&lt;/code&gt; are going to be written recursively! We limited ourselves to considering finite trees to avoid worrying about this for our example. But let's now briefly consider what happens otherwise. By the results in the paper, we can still use a guarded recursive traverse in the writer monad, which will produce a potentially productive stream of results -- one where there may be arbitrarily many &lt;code&gt;Later&lt;/code&gt; steps between each result. Further, a guarded recursive &lt;code&gt;minimum&lt;/code&gt; on such a stream, or even on a necessarily productive &lt;code&gt;Stream&lt;/code&gt; as given above, will necessarily produce a value that is potentially infinitely delayed. So without grinding out the detailed equational substitution, we can conclude that the type signature we would have to produce in the case of a potentially infinite tree would in fact be: &lt;code&gt;(Traversable t, Ord a) =&amp;gt; t a -&amp;gt; t (Partial a)&lt;/code&gt; -- where a partial value is one that may be delayed behind an arbitrary (including infinite) sequence of &lt;code&gt;Later&lt;/code&gt;. This in turns tells us that &lt;code&gt;repMin&lt;/code&gt; on a potentially infinite structure would still produce safely the &lt;em&gt;skeleton&lt;/em&gt; of the structure we started with. However, at each individual leaf, the value would potentially be bottom. And, in fact, by standard reasoning (it takes an infinite amount of time to find the minimum of an infinite stream), we can conclude that when &lt;code&gt;repMin&lt;/code&gt; is run on an infinite structure, then indeed each leaf &lt;em&gt;would&lt;/em&gt; be bottom!&lt;/p&gt;
&lt;p&gt;We'll now consider one further example, arising from &lt;a href=&quot;https://scholarworks.brandeis.edu/esploro/outputs/undergraduate/Getting-A-Quick-Fix-On-Comonads/9923880018001921&quot;&gt;work by Kenneth Foner&lt;/a&gt; on fixed points of comonads. In their paper, Foner provides an efficient fixed point operator for comonads with an &quot;apply&quot; operator, but also makes reference to an inefficient version which they believe has the same semantics, and was introduced by Dominic Orchard. This latter operator is extremely simple to define, and so an easy candidate for an example. We'll first recall the methods of comonads, and then introduce Orchard's fixed-point:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    extract :: w a -&amp;gt; a
    duplicate :: w a -&amp;gt; w (w a)
    extend :: (w a -&amp;gt; b) -&amp;gt; w a -&amp;gt; w b

&lt;span class=&quot;hljs-title&quot;&gt;cfix&lt;/span&gt; f :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (w a -&amp;gt; a) -&amp;gt; w a
&lt;span class=&quot;hljs-title&quot;&gt;cfix&lt;/span&gt; f = fix (extend f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the question is -- when does cfix not bottom out? To answer this, we again just change &lt;code&gt;fix&lt;/code&gt; to &lt;code&gt;lfix&lt;/code&gt; and let the typechecker tells us what goes wrong. We quickly discover that our code no longer typechecks, because &lt;code&gt;lfix&lt;/code&gt; enforces we are given a &lt;code&gt;Later (w a)&lt;/code&gt; but the argument to &lt;code&gt;extend f&lt;/code&gt; needs to be a plain old &lt;code&gt;w a&lt;/code&gt;. We ask ghc for the type of the intermediate conversion function necessary, and arrive at the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lcfix&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; (w b) -&amp;gt; w a) -&amp;gt; (w a -&amp;gt; b) -&amp;gt; w b
&lt;span class=&quot;hljs-title&quot;&gt;lcfix&lt;/span&gt; conv f = lfix (extend f . conv)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we discover that comonad fix will not bottom when we can provide some &lt;code&gt;conv&lt;/code&gt; function that is &quot;like the identity&quot; (so it erases away when we strip out the mucking about with &lt;code&gt;Later&lt;/code&gt;) but can send &lt;code&gt;Later (w a) -&amp;gt; w b&lt;/code&gt;. If we choose to unify &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, then this property (of some type to be equipped with an &quot;almost identity&quot; between it and it delayed by a &lt;code&gt;Later&lt;/code&gt;) is examined in the paper at some length under the name &quot;stability&quot; -- and our conclusion is that cfix will terminate when the type &lt;code&gt;w a&lt;/code&gt; is stable (which is to say that it in one way or another represents a potentially partial value). Also from the paper, we know that one easy way to get stability is when the type &lt;code&gt;w&lt;/code&gt; is &lt;code&gt;Predictable&lt;/code&gt; -- i.e. when it has an &quot;almost identity&quot; map &lt;code&gt;Later (w a) -&amp;gt; w (Later a)&lt;/code&gt; and when &lt;code&gt;a&lt;/code&gt; itself is stable. This handles most uses of comonad fix -- since functors of &quot;fixed shape&quot; (otherwise known as representable, or iso to &lt;code&gt;r -&amp;gt; a&lt;/code&gt; for a fixed &lt;code&gt;r&lt;/code&gt;) are all stable. And the stability condition on the underlying &lt;code&gt;a&lt;/code&gt; tells us that even though we'll get out a perfectly good spine, whether or not there will be a bottom value at any given location in the resultant &lt;code&gt;w a&lt;/code&gt; depends on the precise function being passed in.&lt;/p&gt;
&lt;p&gt;In fact, if we simply start with the idea of predictability in hand, we can specialize the above code in a different way, by taking &lt;code&gt;predict&lt;/code&gt; itself to be our conversion function, and unifying &lt;code&gt;b&lt;/code&gt; with &lt;code&gt;Later a&lt;/code&gt;, which yields the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lcfix2&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Predict&lt;/span&gt; w) =&amp;gt; (w (&lt;span class=&quot;hljs-type&quot;&gt;Later&lt;/span&gt; a) -&amp;gt; a) -&amp;gt; w a
&lt;span class=&quot;hljs-title&quot;&gt;lcfix2&lt;/span&gt; f = lfix (extend f . predict)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This signature is nice because it does not require stability -- i.e. there is no possibility of partial results. Further, it is particularly suggestive -- it looks almost like that of &lt;code&gt;lfix&lt;/code&gt; but lifts both the input to the argument and the output of the fixed-point up under a &lt;code&gt;w&lt;/code&gt;. This warns us how hard it is to get useful values out of fixing a comonad -- in particular, just as with our &lt;code&gt;lfix&lt;/code&gt; itself, we can't directly pattern match on the values we are taking fixed points of, but instead only use them in constructing larger structures.&lt;/p&gt;
&lt;p&gt;These examples illustrate both the power of the internal guarded recursion approach, and also some of its limits. It can tell us a lot of high level information about what does and doesn't produce bottoms, and it can produce conditions under which bottoms will never occur. However, there are also cases where we have code that sometimes bottoms, depending on specific functions it is passed -- the fact that it potentially bottoms is represented in the type, but the exact conditions under which bottoms will or will not occur aren't able to be directly &quot;read off&quot;. In fact, in the references to the paper, there are much richer variants of guarded recursion that allow more precision in typing various sorts of recursive functions, and of course there is are general metamathematical barriers to going sufficiently far -- a typing system rich enough to say if any integer function terminates is also rich enough to say if e.g. the collatz conjecture is true or not! But with all those caveats in mind, I think this is still a useful tool that doesn't only have theoretical properties, but also practical use. The next time you have a tricky recursive function that you're &lt;em&gt;pretty sure&lt;/em&gt; terminates, try these simple steps: 1) rewrite to use explicit fixed points; 2) change those to guarded recursive fixed points; 3) let ghc guide you in fixing the types; 4) see what you learn!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2022/internalized-guarded-recursion-for-equational-reasoning/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Across the Kmettverse</title><link>https://comonad.com/reader/talks/kmett-2022-functional-futures/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2022-functional-futures/</guid><pubDate>Thu, 18 Aug 2022 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 August 2022 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;jZrCVp5ekbA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jZrCVp5ekbA&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Across the Kmettverse with Edward Kmett — Functional Futures / Serokell.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jZrCVp5ekbA&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://podcasts.apple.com/us/podcast/across-the-kmettverse-with-edward-kmett/id1606772921?i=1000576527907&quot;&gt;audio&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://serokell.io/blog/across-the-kmettverse-with-edward-kmett&quot;&gt;edited transcript&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2022-functional-futures/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The current state of the Haskell Foundation</title><link>https://comonad.com/reader/talks/youtube-AweAVW4Pig8/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-AweAVW4Pig8/</guid><pubDate>Wed, 05 Jan 2022 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Andrew Boardman · 5 January 2022&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;AweAVW4Pig8&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=AweAVW4Pig8&quot;&gt;Watch on YouTube&lt;/a&gt; · 60 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;From the 1/5/22 meetup&lt;br&gt;
In a wild and creative talk, Andrew Boardman lets us know about the current state of the Haskell Foundation and its future plans.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-AweAVW4Pig8/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Programming with Tactics</title><link>https://comonad.com/reader/talks/youtube-BiH_A36zKwI/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-BiH_A36zKwI/</guid><pubDate>Wed, 27 Oct 2021 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Reed Mullanix · 27 October 2021&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;BiH_A36zKwI&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=BiH_A36zKwI&quot;&gt;Watch on YouTube&lt;/a&gt; · 65 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;From the 10/27/21 meetup&lt;br&gt;
Reed Mullanix talks about programming with Tactics in Haskell especially concerning their use in Haskell Language Server.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-BiH_A36zKwI/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Taste of Linear Optics</title><link>https://comonad.com/reader/talks/linear-optics-bx-2021/</link><guid isPermaLink="false">https://comonad.com/reader/talks/linear-optics-bx-2021/</guid><pubDate>Mon, 21 Jun 2021 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 21 June 2021&lt;/p&gt;&lt;p&gt;Keynote slides on linear logic, Haskell, and optics, presented at Bx 2021.&lt;/p&gt;&lt;p&gt;&lt;a class=&quot;document-download&quot; href=&quot;https://comonad.com/assets/documents/linear-optics-2021.pdf&quot;&gt;Read the slides (PDF · 47 pages)&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/documents/linear-optics-2021.pdf&quot; download=&quot;&quot;&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/linear-optics-bx-2021/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cadenza: Building Fast Functional Languages Fast</title><link>https://comonad.com/reader/talks/cadenza-yow-2020/</link><guid isPermaLink="false">https://comonad.com/reader/talks/cadenza-yow-2020/</guid><pubDate>Fri, 24 Jul 2020 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 24 July 2020&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;25RmUl88jSw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=25RmUl88jSw&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Cadenza: Building Fast Functional Languages Fast — YOW! Lambda Jam 2020, online.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=25RmUl88jSw&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/cadenza-yow-2020/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Guanxi: Logic Programming in Haskell — Part 4 of 4</title><link>https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/</link><guid isPermaLink="false">https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/</guid><pubDate>Thu, 20 Jun 2019 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 20 June 2019&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;TnohBRvoUJk&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=TnohBRvoUJk&quot;&gt;Watch on YouTube&lt;/a&gt; · 52 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;nav aria-label=&quot;Talk series&quot;&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/&quot;&gt;Part 1&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/&quot;&gt;Part 2&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/&quot;&gt;Part 3&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/&quot; aria-current=&quot;page&quot;&gt;Part 4&lt;/a&gt;&lt;/nav&gt;&lt;p&gt;Monadic Party 2019 - &lt;a href=&quot;https://monadic.party/&quot;&gt;https://monadic.party&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=TnohBRvoUJk&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/guanxi&quot;&gt;related workshop subject source repository&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Guanxi: Logic Programming in Haskell — Part 3 of 4</title><link>https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/</link><guid isPermaLink="false">https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/</guid><pubDate>Thu, 20 Jun 2019 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 20 June 2019&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;c3UE41eYXHA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=c3UE41eYXHA&quot;&gt;Watch on YouTube&lt;/a&gt; · 46 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;nav aria-label=&quot;Talk series&quot;&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/&quot;&gt;Part 1&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/&quot;&gt;Part 2&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/&quot; aria-current=&quot;page&quot;&gt;Part 3&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/&quot;&gt;Part 4&lt;/a&gt;&lt;/nav&gt;&lt;p&gt;Monadic Party 2019 - &lt;a href=&quot;https://monadic.party/&quot;&gt;https://monadic.party&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=c3UE41eYXHA&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/guanxi&quot;&gt;related workshop subject source repository&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Guanxi: Logic Programming in Haskell — Part 2 of 4</title><link>https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/</link><guid isPermaLink="false">https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/</guid><pubDate>Tue, 18 Jun 2019 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 June 2019&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;s5OnhepyL7w&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=s5OnhepyL7w&quot;&gt;Watch on YouTube&lt;/a&gt; · 43 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;nav aria-label=&quot;Talk series&quot;&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/&quot;&gt;Part 1&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/&quot; aria-current=&quot;page&quot;&gt;Part 2&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/&quot;&gt;Part 3&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/&quot;&gt;Part 4&lt;/a&gt;&lt;/nav&gt;&lt;p&gt;Monadic Party 2019 - &lt;a href=&quot;https://monadic.party/&quot;&gt;https://monadic.party&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=s5OnhepyL7w&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/guanxi&quot;&gt;related workshop subject source repository&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Guanxi: Logic Programming in Haskell — Part 1 of 4</title><link>https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/</guid><pubDate>Tue, 18 Jun 2019 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 June 2019&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;D7rlJWc3474&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=D7rlJWc3474&quot;&gt;Watch on YouTube&lt;/a&gt; · 47 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;nav aria-label=&quot;Talk series&quot;&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/&quot; aria-current=&quot;page&quot;&gt;Part 1&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-2/&quot;&gt;Part 2&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-3/&quot;&gt;Part 3&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-4/&quot;&gt;Part 4&lt;/a&gt;&lt;/nav&gt;&lt;p&gt;Monadic Party 2019 - &lt;a href=&quot;https://monadic.party/&quot;&gt;https://monadic.party&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=D7rlJWc3474&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/guanxi&quot;&gt;related workshop subject source repository&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/2019-monadic-party-guanxi-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 25: Guanxi Review</title><link>https://comonad.com/reader/talks/live-coding-25/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-25/</guid><pubDate>Wed, 03 Apr 2019 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 3 April 2019 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;ISNYPKiE0YU&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ISNYPKiE0YU&quot;&gt;Watch on YouTube&lt;/a&gt; · 80 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This is a review of the last few streams, where we go through what it is that we've managed to build during my obsession with Logic Programming. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-25/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 24: Dancing with Decision Diagrams</title><link>https://comonad.com/reader/talks/live-coding-24/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-24/</guid><pubDate>Thu, 13 Dec 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 13 December 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;DTm_Fe7hdIY&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DTm_Fe7hdIY&quot;&gt;Watch on YouTube&lt;/a&gt; · 185 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;We manage to implement the &quot;Dancing with Decision Diagrams&quot; paper in guanxi. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-24/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 23: Dancing Links, Part 2</title><link>https://comonad.com/reader/talks/live-coding-23/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-23/</guid><pubDate>Thu, 13 Dec 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 13 December 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;IoXDNWhN0aw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=IoXDNWhN0aw&quot;&gt;Watch on YouTube&lt;/a&gt; · 338 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;More work on Dancing Links for guanxi. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-23/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 22: Dancing Links</title><link>https://comonad.com/reader/talks/live-coding-22/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-22/</guid><pubDate>Thu, 06 Dec 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 6 December 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;gxHE3uguDbg&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gxHE3uguDbg&quot;&gt;Watch on YouTube&lt;/a&gt; · 298 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Implementing Knuth's algorithm X with Dancing Links in C++. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-22/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 21: Relational Programming, Part 6</title><link>https://comonad.com/reader/talks/live-coding-21/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-21/</guid><pubDate>Wed, 05 Dec 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 5 December 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;UAcZUK7x6xw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=UAcZUK7x6xw&quot;&gt;Watch on YouTube&lt;/a&gt; · 167 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Reviewing the last couple of days work on delimited continuations, and then implementing explicit sharing in the style of &lt;a href=&quot;http://www-ps.informatik.uni-kiel.de/~sebf/pub/icfp09.html&quot;&gt;http://www-ps.informatik.uni-kiel.de/~sebf/pub/icfp09.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Code: &lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;http://github.com/ekmett/guanxi&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-21/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 20: Relational Programming, Part 5</title><link>https://comonad.com/reader/talks/live-coding-20/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-20/</guid><pubDate>Wed, 05 Dec 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 5 December 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;YUgZrsDhn4o&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YUgZrsDhn4o&quot;&gt;Watch on YouTube&lt;/a&gt; · 137 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Back from Iceland, where I managed to get more done on guanxi. Most of this stream is devoted to describing the changes made thus far and less to actually implementing new stuff.   -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-20/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 19: Relational Programming, Part 4 (Soul of a New Machine)</title><link>https://comonad.com/reader/talks/live-coding-19/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-19/</guid><pubDate>Mon, 19 Nov 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 19 November 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;P2Ak8sEolkI&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=P2Ak8sEolkI&quot;&gt;Watch on YouTube&lt;/a&gt; · 100 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;More live-coding. New computer, so I'm currently playing with my development environment to see how well it works for the stream. In the meantime, we wander back to  guanxi and play with the Key monad implementation, and tweak a small Overton style finite domain solver to have stronger types and a more propagator-like implementation strategy. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-19/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 17: Relational Programming, Part 3</title><link>https://comonad.com/reader/talks/live-coding-17/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-17/</guid><pubDate>Fri, 16 Nov 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 16 November 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;wkHRM_5CV84&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wkHRM_5CV84&quot;&gt;Watch on YouTube&lt;/a&gt; · 107 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;More relational programming. We finish fleshing out the notion of a &quot;Log&quot; to help us steal the power of seminaive evaluation from Datalog for our propagator framework.&lt;/p&gt;
&lt;p&gt;Project at &lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;http://github.com/ekmett/guanxi&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-17/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 18: Nominal Sets</title><link>https://comonad.com/reader/talks/live-coding-18/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-18/</guid><pubDate>Sat, 03 Nov 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 3 November 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;3Zreblm0Ux0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=3Zreblm0Ux0&quot;&gt;Watch on YouTube&lt;/a&gt; · 611 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Nominal sets are about dealing with name capture in a principled way, based on permutations of 'atoms' or 'names'.&lt;/p&gt;
&lt;p&gt;We spent the night refactoring my &lt;code&gt;nominal&lt;/code&gt; library to use a new underlying notion of support and to use a more uniform notion of patricia tries. The tries are currently subbed out for a placeholder, but everything else now works.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ekmett/name&quot;&gt;https://github.com/ekmett/name&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/name&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-18/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 16: Relational Programming, Part 2</title><link>https://comonad.com/reader/talks/live-coding-16/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-16/</guid><pubDate>Thu, 04 Oct 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 4 October 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;yTlTtmVX3vA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yTlTtmVX3vA&quot;&gt;Watch on YouTube&lt;/a&gt; · 289 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Picking up from where we left off last stream (&quot;Back from ICFP&quot;) we continue forging on building a little library for relational programming in the spirit if not the style of minikanren. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-16/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 15: Back from ICFP</title><link>https://comonad.com/reader/talks/live-coding-15/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-15/</guid><pubDate>Mon, 01 Oct 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 1 October 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;JYWSqT1FIug&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JYWSqT1FIug&quot;&gt;Watch on YouTube&lt;/a&gt; · 178 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Working towards a little relational programming library as an excuse to write some code after returning from ICFP.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;http://github.com/ekmett/guanxi&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://github.com/ekmett/guanxi&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-15/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>There and Back Again: Regular and Inverse Semigroups</title><link>https://comonad.com/reader/talks/there-and-back-again-lambda-world-2018/</link><guid isPermaLink="false">https://comonad.com/reader/talks/there-and-back-again-lambda-world-2018/</guid><pubDate>Tue, 18 Sep 2018 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 September 2018&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;HGi5AxmQUwU&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=HGi5AxmQUwU&quot;&gt;Watch on YouTube&lt;/a&gt; · 47 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This keynote by Edward Kmett took place at Lambda World Seattle on September 18th, 2018 at the Living Computers Museum in Washington.&lt;/p&gt;
&lt;p&gt;Opening Keynote: There and Back Again&lt;/p&gt;
&lt;p&gt;Mathematicians usually teach abstract algebra from groups and build up from there. Having inverses allows them to prove many non-trivial results. Functional programmers more often descend to working with monoids, or even semigroups. They give up the power of inverses to gain many more examples. You don't often hear about the shadowy realm between. Perfect inverses don't always exist, nor do we want them to. Going on a journey and returning rarely leaves the protagonist unchanged. If it does, this is usually taken as a poor example of the author's craft. We'll explore the middle-ground of regular and inverse semigroups, inverse monoids, even inverse categories. In this space where inverses may not invert, we'll develop examples and counter-examples. We'll gain some insight into spoken Australian English along the way. Join us.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/haskell/comments/9x684a/edward_kmett_there_and_back_again_regular_and/&quot;&gt;Discussion and author clarifications&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/there-and-back-again-lambda-world-2018/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 14.3: Succinct Serialization, Part 6</title><link>https://comonad.com/reader/talks/live-coding-14-3/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-14-3/</guid><pubDate>Sun, 26 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 26 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;10Cj33G9G-M&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=10Cj33G9G-M&quot;&gt;Watch on YouTube&lt;/a&gt; · 54 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Undoing a fair bit of the damage we did from the last couple of streams and trying to incorporate the things we did like. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-14-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 14.2: Succinct Serialization, Part 6</title><link>https://comonad.com/reader/talks/live-coding-14-2/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-14-2/</guid><pubDate>Sun, 26 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 26 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;GCPClbek0Rg&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=GCPClbek0Rg&quot;&gt;Watch on YouTube&lt;/a&gt; · 4 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Undoing a fair bit of the damage we did from the last couple of streams and trying to incorporate the things we did like. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-14-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 14.1: Succinct Serialization, Part 6</title><link>https://comonad.com/reader/talks/live-coding-14-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-14-1/</guid><pubDate>Sun, 26 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 26 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;bfooJoXCKpk&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=bfooJoXCKpk&quot;&gt;Watch on YouTube&lt;/a&gt; · 9 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Undoing a fair bit of the damage we did from the last couple of streams and trying to incorporate the things we did like. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-14-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 13: Succinct Serialization, Part 5</title><link>https://comonad.com/reader/talks/live-coding-13/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-13/</guid><pubDate>Sat, 25 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 25 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;i1y3_72T1l4&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=i1y3_72T1l4&quot;&gt;Watch on YouTube&lt;/a&gt; · 271 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The new generic programming approach appears to be a bust.   -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-13/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 12: Succinct Serialization, Part 4</title><link>https://comonad.com/reader/talks/live-coding-12/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-12/</guid><pubDate>Sat, 25 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 25 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;OrY1U2qLnps&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=OrY1U2qLnps&quot;&gt;Watch on YouTube&lt;/a&gt; · 191 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Broadcast in the middle of the week. We mostly spent this time exploring building an alternative form of generic programming, because of a desire for better strictness info.   -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-12/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 11: Succinct Serialization, Part 3</title><link>https://comonad.com/reader/talks/live-coding-11/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-11/</guid><pubDate>Mon, 20 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 20 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;AfCCNACoDZc&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=AfCCNACoDZc&quot;&gt;Watch on YouTube&lt;/a&gt; · 358 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;In this stream we went off and found a nicer format for succinct serialization without quite so many parentheses.&lt;/p&gt;
&lt;p&gt;Then we spent a lot of time fiddling with generics. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-11/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 10: Succinct Serialization, Part 2</title><link>https://comonad.com/reader/talks/live-coding-10/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-10/</guid><pubDate>Mon, 13 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 13 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;pm-4WV67T_Q&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=pm-4WV67T_Q&quot;&gt;Watch on YouTube&lt;/a&gt; · 191 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;In which we (mostly) convert to using a sum-of-product representation for terms to get a more efficient serialized form. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-10/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 9: Succinct Serialization, Part 1</title><link>https://comonad.com/reader/talks/live-coding-9/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-9/</guid><pubDate>Sun, 05 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 5 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;rMCGmQhgv2I&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rMCGmQhgv2I&quot;&gt;Watch on YouTube&lt;/a&gt; · 479 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Continuing on from last time, we build the bulk of a library for lazily (de)serializing data with succinct data structures. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-9/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 7: More Machines</title><link>https://comonad.com/reader/talks/live-coding-7/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-7/</guid><pubDate>Thu, 02 Aug 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 2 August 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;YYSWNXcKOWw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YYSWNXcKOWw&quot;&gt;Watch on YouTube&lt;/a&gt; · 82 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This is a short stream in which we mostly flailed around trying to understand why the division between&quot;bound&quot; and &quot;free&quot; variables in a slightly closer to the hardware abstract machine wasn't quite where we thought it was.   -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-7/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 8: Succinct Data Structures and Dynamization</title><link>https://comonad.com/reader/talks/live-coding-8/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-8/</guid><pubDate>Mon, 30 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 30 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;9MKEmNNJgFc&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=9MKEmNNJgFc&quot;&gt;Watch on YouTube&lt;/a&gt; · 154 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;A bit of a crash course on succinct data structures and dynamization schemes. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-8/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 6: CEK Machines</title><link>https://comonad.com/reader/talks/live-coding-6/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-6/</guid><pubDate>Sun, 22 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 22 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;PwD7D7XUzec&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PwD7D7XUzec&quot;&gt;Watch on YouTube&lt;/a&gt; · 105 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Implementing a CEK machine in Haskell in incrementally more typed fashions. A CEK machine is a sort of standard virtual machine model for implementing interpreters using small step semantics. At the end we touch briefly on Futamura projections and big-step semantics.&lt;/p&gt;
&lt;p&gt;Untyped CEK: &lt;a href=&quot;https://gist.github.com/ekmett/f081b5e36bac3fed1ea6b21eb25327c6&quot;&gt;https://gist.github.com/ekmett/f081b5e36bac3fed1ea6b21eb25327c6&lt;/a&gt;&lt;br&gt;
Typed CEK: &lt;a href=&quot;https://gist.github.com/ekmett/ac2bef9de19881d6286044a06936dd55&quot;&gt;https://gist.github.com/ekmett/ac2bef9de19881d6286044a06936dd55&lt;/a&gt;&lt;br&gt;
Matt Might on CEK Machines in Haskell: &lt;a href=&quot;http://matt.might.net/articles/cek-machines/&quot;&gt;http://matt.might.net/articles/cek-machines/&lt;/a&gt;&lt;br&gt;
Dan Piponi on Futamura Projections: &lt;a href=&quot;http://blog.sigfpe.com/2009/05/three-projections-of-doctor-futamura.html&quot;&gt;http://blog.sigfpe.com/2009/05/three-projections-of-doctor-futamura.html&lt;/a&gt;&lt;br&gt;
Paul Chiusano on Unison's Runtime: &lt;a href=&quot;https://www.youtube.com/watch?v=knqlWboqf_U&quot;&gt;https://www.youtube.com/watch?v=knqlWboqf_U&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://gist.github.com/ekmett/f081b5e36bac3fed1ea6b21eb25327c6&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://gist.github.com/ekmett/ac2bef9de19881d6286044a06936dd55&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-6/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 5.2: Propagators</title><link>https://comonad.com/reader/talks/live-coding-5-2/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-5-2/</guid><pubDate>Sun, 15 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 15 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;-DBsKQMh6n4&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-DBsKQMh6n4&quot;&gt;Watch on YouTube&lt;/a&gt; · 143 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The &quot;Art of the Propagator&quot;, Part 2/2.&lt;br&gt;
-- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-5-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 5.1: Propagators</title><link>https://comonad.com/reader/talks/live-coding-5-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-5-1/</guid><pubDate>Sun, 15 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 15 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;rAQoSjnBvtA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rAQoSjnBvtA&quot;&gt;Watch on YouTube&lt;/a&gt; · 16 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;An introduction to the &quot;Art of the Propagator.&quot; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-5-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 4.2: Q&amp;A</title><link>https://comonad.com/reader/talks/live-coding-4-2/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-4-2/</guid><pubDate>Sun, 08 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 8 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;ylsNMfWMKYc&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ylsNMfWMKYc&quot;&gt;Watch on YouTube&lt;/a&gt; · 22 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Q&amp;amp;A session and organizing topics for next time at the end of the stream, highlighted separately from the &quot;content&quot; of the stream. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-4-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 4.1: Regular and Inverse Semigroups</title><link>https://comonad.com/reader/talks/live-coding-4-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-4-1/</guid><pubDate>Sun, 08 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 8 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;d7JPz3Vq9YI&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=d7JPz3Vq9YI&quot;&gt;Watch on YouTube&lt;/a&gt; · 163 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;We build up the notion of regular and inverse semigroups in Haskell and start to explore some of their extra structure, then dive a little into incremental parsing, a particularly pragmatic problem domain where they arise more often than you'd think. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-4-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 3: Authenticated Computation</title><link>https://comonad.com/reader/talks/live-coding-3/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-3/</guid><pubDate>Sun, 01 Jul 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 1 July 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;StmmK1a1Bm0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=StmmK1a1Bm0&quot;&gt;Watch on YouTube&lt;/a&gt; · 230 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Building a little library for authenticated computations in Haskell.&lt;/p&gt;
&lt;p&gt;This should give a sense of different approaches to API design in Haskell, and some of the trade-offs between fundeps, type families, backpack, data families, etc. as I pretty much wander between all of them while trying to come up with a nice API.&lt;/p&gt;
&lt;p&gt;Original Paper: &lt;a href=&quot;http://www.cs.umd.edu/~mwh/papers/gpads.pdf&quot;&gt;http://www.cs.umd.edu/~mwh/papers/gpads.pdf&lt;/a&gt;&lt;br&gt;
Bob Atkey's Library: &lt;a href=&quot;https://bentnib.org/posts/2016-04-12-authenticated-data-structures-as-a-library.html&quot;&gt;https://bentnib.org/posts/2016-04-12-authenticated-data-structures-as-a-library.html&lt;/a&gt;&lt;br&gt;
Code from the stream: &lt;a href=&quot;https://github.com/ekmett/auth&quot;&gt;https://github.com/ekmett/auth&lt;/a&gt; -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/ekmett/auth&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Combinators Revisited</title><link>https://comonad.com/reader/talks/combinators-zurihac-2018/</link><guid isPermaLink="false">https://comonad.com/reader/talks/combinators-zurihac-2018/</guid><pubDate>Sun, 10 Jun 2018 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 10 June 2018&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;PA1Fc7DNKtA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PA1Fc7DNKtA&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Combinators Revisited — ZuriHac 2018.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PA1Fc7DNKtA&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/combinators-zurihac-2018/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Combinators Revisited</title><link>https://comonad.com/reader/talks/combinators-yow-2018/</link><guid isPermaLink="false">https://comonad.com/reader/talks/combinators-yow-2018/</guid><pubDate>Tue, 22 May 2018 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 22 May 2018&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;zhj_tUMwTe0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zhj_tUMwTe0&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Combinators Revisited — YOW! Lambda Jam 2018, Sydney.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://yowconference.com.au/slides/yowlambdajam2018/Kmett-Combinators.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://slides.yowconference.com/yowlambdajam2018/Kmett-Combinators.pdf&quot;&gt;slides pdf redirect&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zhj_tUMwTe0&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/combinators-yow-2018/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 2.2: Q&amp;A</title><link>https://comonad.com/reader/talks/live-coding-2-2/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-2-2/</guid><pubDate>Sun, 06 May 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 6 May 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;2_R6jvI5WdU&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=2_R6jvI5WdU&quot;&gt;Watch on YouTube&lt;/a&gt; · 157 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;A live Q&amp;amp;A session about all things Haskell. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-2-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 2.1: Q&amp;A</title><link>https://comonad.com/reader/talks/live-coding-2-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-2-1/</guid><pubDate>Sun, 06 May 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 6 May 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;d1T9JhurjE0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=d1T9JhurjE0&quot;&gt;Watch on YouTube&lt;/a&gt; · 85 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;A live Q&amp;amp;A session about all things Haskell. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-2-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Live Coding — Session 1: Commutativity</title><link>https://comonad.com/reader/talks/live-coding-1/</link><guid isPermaLink="false">https://comonad.com/reader/talks/live-coding-1/</guid><pubDate>Sun, 29 Apr 2018 12:00:00 GMT</pubDate><category>Stream</category><description>&lt;p&gt;Edward Kmett · 29 April 2018 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Nv5tf8pvgrY&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Nv5tf8pvgrY&quot;&gt;Watch on YouTube&lt;/a&gt; · 232 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Building a library for commutative applicative functors and general chat about the Haskell programming language.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/ekmett/abelian&quot;&gt;http://github.com/ekmett/abelian&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This highlight starts right after the wrangling with the streaming environment wrapped up. -- Watch live at &lt;a href=&quot;https://www.twitch.tv/ekmett&quot;&gt;https://www.twitch.tv/ekmett&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://github.com/ekmett/abelian&quot;&gt;Code from the stream&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/live-coding-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Computational Quadrinitarianism (Curious Correspondences go Cubical)</title><link>https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/</link><guid isPermaLink="false">https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/</guid><pubDate>Tue, 16 Jan 2018 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 16 January 2018&lt;/p&gt;&lt;p&gt;Back in 2011, in an influential blog post [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#1&quot;&gt;1&lt;/a&gt;], Robert Harper coined the term &quot;computational trinitarianism&quot; to describe an idea that had been around a long time — that the connection between programming languages, logic, and categories, most famously expressed in the Curry-Howard-Lambek correspondence — should guide the practice of researchers into computation. In particular &quot;any concept arising in one aspect should have meaning from the perspective of the other two&quot;. This was especially satisfying to those of us trying learning categorical semantics and often finding it disappointing how little it is appreciated in the computer science community writ large.&lt;/p&gt;
&lt;h4 id=&quot;1-categories&quot;&gt;1. Categories&lt;/h4&gt;
&lt;p&gt;Over the years I've thought about trinitarianism a lot, and learned from where it fails to work as much as where it succeeds. One difficulty is that learning to read a logic like a type theory, or vice versa, is almost a definitional trick, because it occurs at the level of reinterpretation of syntax. With categories it is typically not so easy. (There is a straightforward version of categorical semantics like this — yielding &quot;syntactic categories&quot; — but it is difficult to connect it to the broader world of categorical semantics, and often it is sidestepped in favor of deeper models.)&lt;/p&gt;
&lt;p&gt;One thing I came to realize is that there is no one notion of categorical semantics — the way in which the simply typed lambda calculus takes models in cartesian closed categories is fundamentally unlike the way in which linear logics take models in symmetric monoidal categories. If you want to study models of dependent type theories, you have a range of approaches, only some of which have been partially unified by Ahrens, Lumsdaine and Voevodsky in particular [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#2&quot;&gt;2&lt;/a&gt;]. And then there are the LCCC models pioneered by Seely for extensional type theory, not to mention the approach that takes semantics directly in toposes, or in triposes (the latter having been invented to unify a variety of structures, and in the process giving rise to still more questions). And then there is the approach that doesn't use categories at all, but multicategories.&lt;/p&gt;
&lt;p&gt;Going the other way, we also run into obstacles: there is a general notion, opposite to the &quot;syntactic category&quot; of a type theory, which is the &quot;internal logic&quot; of a category. But depending on the form of category, &quot;internal logic&quot; can take many forms. If you are in a topos, there is a straightforward internal logic called the Mitchell–Bénabou language. In this setting, most &quot;logical&quot; operations factor through the truth-lattice of the subobject classifier. This is very convenient, but if you don't have a proper subobject classifier, then you are forced to reach for other interpretations. As such, it is not infrequently the case that we have a procedure for deriving a category from some logical theory, and a procedure for constructing a logical theory from some category, but there is no particular reason to expect that where we arrive, when we take the round-trip, is close to, much less precisely, where we began.&lt;/p&gt;
&lt;h4 id=&quot;2-spaces-logics&quot;&gt;2. Spaces, Logics&lt;/h4&gt;
&lt;p&gt;Over the past few years I've been in a topos theory reading group. In the course of this, I've realized at least one problem with all the above (by no means the only one) — Harper's holy trinity is fundamentally incomplete. There is another structure of interest — of equal weight to categories, logics, and languages — which it is necessary to understand to see how everything fits. This structure is &lt;em&gt;spaces&lt;/em&gt;. I had thought that it was a unique innovation of homotopy type theory to consider logics (resp. type theories) that took semantics in spaces. But it turns out that I just didn't know the history of constructive logic very well. In fact, in roughly the same period that Curry was exploring the relationship of combinatory algebras to logic, Alfred Tarski and Marshall Stone were developing &lt;em&gt;topological&lt;/em&gt; models for intuitionistic logic, in terms of what we call Heyting Algebras [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#3&quot;&gt;3&lt;/a&gt;] [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#4&quot;&gt;4&lt;/a&gt;]. And just as, as Harper explained, logic, programming and category theory give us insights into implication in the form of entailment, typing judgments, and morphisms, so to, as we will see, do spaces.&lt;/p&gt;
&lt;p&gt;A Heyting algebra is a special type of distributive lattice (partially ordered set, equipped with meet and join operations, such that meet and join distribute over one another) which has an implication operation that satisfies curry/uncurry adjointness — i.e. such that c ∧ a ≤ b &amp;lt; -&amp;gt; c ≤ a → b. (Replace meet here by &quot;and&quot; (spelled &quot;*&quot;), and ≤ by ⊢ and we have the familiar type-theoretic statement that c * a ⊢ b &amp;lt; -&amp;gt; c ⊢ a → b).&lt;/p&gt;
&lt;p&gt;If you haven't encountered this before, it is worth unpacking. Given a set, we equip it with a partial order by specifying a &quot;≤&quot; operation, such that a ≤ a, if a ≤ b and b ≤ a, then a = b, and finally that if a ≤ b and b ≤ c, then a ≤ c. We can think of such things as Hasse diagrams — a bunch of nodes with some lines between them that only go upwards. If a node b is reachable from a node a by following these upwards lines, then a ≤ b. This &quot;only upwards&quot; condition is enough to enforce all three conditions. We can define ∨ (join) as a binary operation that takes two nodes, and gives a node a ∨ b that is greater than either node, and furthermore is the &lt;em&gt;uniquely least&lt;/em&gt; node greater than both of them. (Note: A general partial order may have many pairs of nodes that do not have any node greater than both of them, or may that may have more than one incomparable node greater than them.) We can define ∧ (meet) dually, as the uniquely greatest node less than both of them. If all elements of a partially ordered set have a join and meet, we have a lattice.&lt;/p&gt;
&lt;p&gt;It is tempting to read meet and join as &quot;and&quot; and &quot;or&quot; in logic. But these logical connectives satisfy an additional important property — distributivity: a &amp;amp; (b | c) = (a &amp;amp; b) | (a &amp;amp; c). (By the lattice laws, the dual property with and swapped with or is also implied). Translated for lattices this reads: a ∧ (b ∨ c) = (a ∧ b) ∨ (a ∧ c). Rather than thinking just about boolean logic, we can think about lattices built from sets — with meets as union, join as intersection, and ≤ given by inclusion. It is easy to verify that such lattices are distributive. Furthermore, every distributive lattice can be given (up to isomorphism) as one built out of sets in this way. While a partially ordered set can have a Hasse diagram of pretty arbitrary shape, a lattice is more restrictive — I imagine it as sort of the tiled diamonds of an actual lattice like one might use in a garden, but with some nodes and edges possibly removed.&lt;/p&gt;
&lt;p&gt;Furthermore, there's an amazing result that you can tell if a lattice is distributive by looking for just two prototypical non-distributive lattices as sublattices. If neither is contained in the original lattice, then the lattice is distributed. These tell us how distribution can fail in two canonical ways. The first is three incomparable elements, all of which share a common join (the top) and meet (the bottom). The join of anything but their bottom element with them is therefore the top. Hence if we take the meet of two joins, we still get the top. But the meet of any two non-top elements is the bottom and so, if we take the join of any element with the meet of any other two, we get back to the first element, not all the way to the top, and the equality fails. The second taboo lattice is constructed by having two elements in an ordered relationship, and another incomparable to them — again augmented with a bottom and top. A similar argument shows that if you go one way across the desired entity, you pick out the topmost of the two ordered elements, and the other way yields the bottommost. (The &lt;a href=&quot;https://en.wikipedia.org/wiki/Distributive_lattice#Characteristic_properties&quot;&gt;wikipedia article on distributive lattices&lt;/a&gt; has some very good diagrams to visualize all this). So a distributive lattice has even more structure than before — incomparable elements must have enough meets and joins to prevent these sublattices from appearing, and this forces even more the appearance of a tiled-diamond like structure.&lt;/p&gt;
&lt;p&gt;To get us to a Heyting algebra, we need more structure still — we need implication, which is like an internal function arrow, or an internal ≤ relation. Recall that the equation we want to satisfy is &quot;c ∧ a ≤ b &amp;lt; -&amp;gt; c ≤ a → b&quot;. The idea is that we should be able to read ≤ itself as an &quot;external implication&quot; and so if c and a taken together imply b, &quot;a implies b&quot; is the portion of that implication if we &quot;only have&quot; c. We can see it as a partial application of the external implication. If we have a lattice that permits infinite joins (or just a finite lattice such that we don't need them), then it is straightforward to see how to construct this. To build a → b, we just look at &lt;em&gt;every possible&lt;/em&gt; choice of c that satisfies c ∧ a ≤ b, and then take the join of all of them to be our object a → b. Then, by construction, a → b is necessarily greater than or equal to any c that satisfies the left hand side of the equation. And conversely, any element that a → b is greater than is necessarily one that satisfies the left hand side, and the bi-implication is complete. (This, by the way, gives a good intuition for the definition of an exponential in a category of presheaves). Another way to think of a → b is as the greatest element of the lattice such that a → b ∧ a ≤ b (exercise: relate this to the first definition). It is also a good exercise to explore what happens in certain simple cases — what if a is 0 (false)? What if it is 1? The same as b? Now ask the same questions of b.&lt;/p&gt;
&lt;p&gt;So why is a Heyting algebra a &lt;em&gt;topological&lt;/em&gt; construct? Consider any topological space as given by a collection of open sets, satisfying the usual principles (including the empty set and the total set, and closed under union and finite intersection). These covers have a partial ordering, given by containment. They have unions and intersections (all joins and meets), a top and bottom element (the total space, and the null space). Furthermore, they have an implication operation as described above. As an open set, a → b is given by the meet of all opens c for which a ∧ c ≤ b. (We can think of this as &quot;the biggest context, for which a ⊢ b&quot;). In fact, the axioms for open sets feel almost exactly like the rules we've described for Heyting algebras. It turns out this is only half true — open sets always give Heyting algebras, and we can turn every Heyting algebra into a space. However, in both directions the round trip may take us to somewhere slightly different than where we started. Nonetheless it turns out that if we take complete Heyting algebras where finite meets distribute over infinite joins, we get something called &quot;frames.&quot; And the opposite category of frames yields &quot;locales&quot; — a suitable generalization of topological spaces, first named by John Isbell in 1972 [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#5&quot;&gt;5&lt;/a&gt;]. Spaces that correspond precisely to locales are called &lt;em&gt;sober&lt;/em&gt;, and locales that correspond precisely to spaces are said to have &quot;enough points&quot; or be &quot;spatial locales&quot;.&lt;/p&gt;
&lt;p&gt;In fact, we don't need to fast-forward to 1972 to get some movement in the opposite direction. In 1944, McKinsey and Tarski embarked on a program of &quot;The Algebra of Topology&quot; which sought to describe topological spaces in purely algebraic (axiomatic) terms [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#6&quot;&gt;6&lt;/a&gt;]. The resultant closure algebras (these days often discussed as their duals, interior algebras) provided a semantics for S4 modal logic. [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#7&quot;&gt;7&lt;/a&gt;] A further development in this regard came with Kripke models for logic [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#8&quot;&gt;8&lt;/a&gt;] (though arguably they're really Beth models [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#9&quot;&gt;9&lt;/a&gt;]).&lt;/p&gt;
&lt;p&gt;Here's an easy way to think about Kripke models. Start with any partial ordered set. Now, for each object, instead consider instead all morphisms into it. Since each morphism from any object a to any object b exists only if a ≤ b, and we consider such paths unique (if there are two &quot;routes&quot; showing a ≤ b, we consider them the same in this setting) this amounts to replacing each element a with the set of all elements ≤ a. (The linked pdf does this upside down, but it doesn't really matter). Even though the initial setting may not have been Heyting algebra, this transformed setting &lt;em&gt;is&lt;/em&gt; a Heyting algebra. (In fact, by a special case of the Yoneda lemma!). This yields Kripke models.&lt;/p&gt;
&lt;p&gt;Now consider &quot;collapsings&quot; of elements in the initial partial order — monotone downwards maps taken by sending some elements to other elements less than them in a way that doesn't distort orderings. (I.e. if f(a) ≤ f(b) in the collapsed order, then that means that a ≤ b in the original order). Just as we can lift elements from the initial partial order into their downsets (sets of elements less than them) in the kripkified Heyting Algebra, we can lift our collapsing functions into collapsing functions in our generated Heyting Algebra. With a little work we can see that collapsings in the partial order also yield collapsings in the Heyting Algebra.&lt;/p&gt;
&lt;p&gt;Furthermore, it turns out, more or less, that you can generate every closure algebra in this way. Now if we consider closure algebras a bit (and this shouldn't surprise us if we know about S4), we see that we can always take a to Ca, that if we send a → b, then we can send Ca → Cb, and furthermore that CCa → Ca in a natural way (in fact, they're equal!). So closure algebras have the structure of an idempotent monad. (Note: the arrows here should not be seen as representing internal implication — as above they represent the logical turnstile ⊢ or perhaps, if you're really in a Kripke setting, the forcing turnstile ⊩).&lt;/p&gt;
&lt;p&gt;Now we have a correspondence between logic and computation (Curry-Howard), logic and categories (Lambek-Scott), and logic and spaces (Tarski-Stone). So maybe, instead of Curry-Howard-Lambek, we should speak of Curry-Howard-Lambek-Scott-Tarski-Stone! (Or, if we want to actually bother to say it, just Curry-Howard-Lambek-Stone. Sorry, Tarski and Scott!) Where do the remaining correspondences arise from? A cubical Kan operation, naturally! But let us try to sketch in a few more details.&lt;/p&gt;
&lt;h4 id=&quot;3-spaces-categories&quot;&gt;3. Spaces, Categories&lt;/h4&gt;
&lt;p&gt;All this about monads and Yoneda suggests that there's something categorical going on. And indeed, there is. A poset is, in essence, a &quot;decategorified category&quot; — that is to say, a category where any two objects have at most one morphism between them. I think of it as if it were a balloon animal that somebody let all the air out of. We can pick up the end of our poset and blow into it, inflating the structure back up, and allowing multiple morphisms between each object. If we do so, something miraculous occurs — our arbitrary posets turn into arbitrary categories, and the induced Heyting algebra from their opens turns into the induced category of set-valued presheaves of that category. The resultant structure is a presheaf topos. If we &quot;inflate up&quot; an appropriate notion of a closure operator we arrive at a Grothendieck topos! And indeed, the internal language of a topos is higher-order intuitionistic type theory [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#10&quot;&gt;10&lt;/a&gt;].&lt;/p&gt;
&lt;h4 id=&quot;4-spaces-programming-languages&quot;&gt;4. Spaces, Programming Languages&lt;/h4&gt;
&lt;p&gt;All of this suggests a compelling story: logic describes theories via algebraic syntax. Equipping these theories with various forms of structural operations produces categories of one sort or another, in the form of fibrations. The intuition is that types are spaces, and contexts are &lt;em&gt;also&lt;/em&gt; spaces. And furthermore, types are &lt;em&gt;covered&lt;/em&gt; by the contexts in which their terms may be derived. This is one sense in which we it seems possible to interpret the Meillies/Zeilberger notion of a type refinement system as a functor [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#11&quot;&gt;11&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;But where do programming languages fit in? Programming languages, difficult as it is to sometimes remember, are more than their type theories. They have a semantic of computation as well. For example, a general topos does not have partial functions, or a fixed point combinator. But computations, often, do. This led to one of the first applications of topology to programming languages — the introduction of domain theory, in which terms are special kinds of spaces — directed complete partial orders — and functions obey a special kind of continuity (preservation of directed suprema) that allows us to take their fixed points. But while the category of dcpos is cartesian closed, the category of dcpos with only appropriately continuous morphisms is &lt;em&gt;not&lt;/em&gt;. Trying to resolve this gap, one way or another, seems to have been a theme of research in domain theory throughout the 80s and 90s [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#12&quot;&gt;12&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;Computations can also be concurrent. Topological and topos-theoretic notions again can play an important role. In particular, to consider two execution paths to be &quot;the same&quot; one needs a notion of equivalence. This equivalence can be seen, stepwise, as a topological &quot;two-cell&quot; tracing out at each step an equivalence between the two execution paths. One approach to this is in Joyal, Nielson and Winskel's treatment of open maps [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#13&quot;&gt;13&lt;/a&gt;]. I've also just seen Patrick Schultz and David I. Spivak's &quot;Temporal Type Theory&quot; which seems very promising in this regard [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#14&quot;&gt;14&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;What is the general theme? Computation starts somewhere, and then goes somewhere else. If it stayed in the same place, it would not &quot;compute&quot;. A computation is necessarily a path in some sense. Computational settings describe ways to take maps between spaces, under a suitable notion of topology. To describe the spaces themselves, we need a language — that language is a logic, or a type theory. Toposes are a canonical place (though not the only one) where logics and spaces meet (and where, to a degree, we can even distinguish their &quot;logical&quot; and &quot;spatial&quot; content). That leaves categories as the ambient language in which all this interplay can be described and generalized.&lt;/p&gt;
&lt;h4 id=&quot;5-spaces-categories&quot;&gt;5. Spaces, Categories&lt;/h4&gt;
&lt;p&gt;All the above only sketches the state of affairs up to roughly the mid '90s. The connection to spaces starts in the late 30s, going through logic, and then computation. But the categorical notion of spaces we have is in some sense impoverished. A topos-theoretic generalization of a space still only describes, albeit in generalized terms, open sets and their lattice of subobject relations. Spaces have a whole other structure built on top of that. From their topology we can extract algebraic structures that describe their shape — this is the subject of algebraic topology. In fact, it was in axiomatizing a branch of algebraic topology (homology) that category theory was first compelled to be invented. And the &quot;standard construction&quot; of a monad was first constructed in the study of homology groups (as the Godement resolution).&lt;/p&gt;
&lt;p&gt;What happens if we turn the tools of categorical generalization of algebraic topology on categories themselves? This corresponds to another step in the &quot;categorification&quot; process described above. Where to go from &quot;0&quot; to &quot;1&quot; we took a partially ordered set and allowed there to be multiple maps between objects, to go from &quot;1&quot; to &quot;2&quot; we can now take a category, where such multiple maps exist, and allow there to be multiple maps &lt;em&gt;between maps&lt;/em&gt;. Now two morphisms, say &quot;f . g&quot; and &quot;h&quot; need not merely be equal or not, but they may be &quot;almost equal&quot; with their equality given by a 2-cell. This is just as two homotopies between spaces may themselves be homotopic. And to go from &quot;2&quot; to &quot;3&quot; we can continue the process again. This yields n-categories. An n-category with all morphisms at every level invertible is an (oo,0)-category, or an infinity groupoid. And in many setups this is the same thing as a topological space (and the question of which setup is appropriate falls under the name &quot;homotopy hypothesis&quot; [&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/#15&quot;&gt;15&lt;/a&gt;]). When morphisms at the first level (the category level) can have direction (just as in normal categories) then those are (oo,1)-categories, and the correspondence between groupoids and spaces is constructed as an equivalence of such categories. These too have direct topological content, and one setting in which this is especially apparent is that of quasi-categories, which are (oo,1)-categories that are built directly from simplicial sets — an especially nice categorical model of spaces (the simplicial sets at play here are those that satisfy a &quot;weak&quot; Kan condition, which is a way of asking that composition behave correctly).&lt;/p&gt;
&lt;p&gt;It is in these generalized (oo,1)-toposes that homotopy type theory takes its models. And, it is hypothesized that a suitable version of HoTT should in fact be the initial model (or &quot;internal logic&quot;) of an &quot;elementary infinity topos&quot; when we finally figure out how to describe what such a thing is.&lt;/p&gt;
&lt;p&gt;So perhaps it is not that we should be computational trinitarians, or quadrinitarians. Rather, it is that the different aspects which we examine — logic, languages, categories, spaces — only appear as distinct manifestations when viewed at a low dimensionality. In the untruncated view of the world, the modern perspective is, perhaps, topological pantheism — spaces are in all things, and through spaces, all things are made as one.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to James Deikun and Dan Doel for helpful technical and editorial comments&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[&lt;span id=&quot;1&quot;&gt;&lt;/span&gt;1] &lt;a href=&quot;https://existentialtype.wordpress.com/2011/03/27/the-holy-trinity/&quot;&gt;https://existentialtype.wordpress.com/2011/03/27/the-holy-trinity/&lt;br&gt;
[&lt;/a&gt;&lt;span id=&quot;2&quot;&gt;&lt;/span&gt;2] &lt;a href=&quot;https://arxiv.org/abs/1705.04310&quot;&gt;https://arxiv.org/abs/1705.04310&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;3&quot;&gt;&lt;/span&gt;3] &lt;a href=&quot;http://www.sciacchitano.it/Tempo/Aussagenkalk%C3%BCl%20Topologie.pdf&quot;&gt;http://www.sciacchitano.it/Tempo/Aussagenkalk%C3%BCl%20Topologie.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;4&quot;&gt;&lt;/span&gt;4] &lt;a href=&quot;https://eudml.org/doc/27235&quot;&gt;https://eudml.org/doc/27235&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;5&quot;&gt;&lt;/span&gt;5] &lt;a href=&quot;http://www.mscand.dk/article/view/11409&quot;&gt;http://www.mscand.dk/article/view/11409&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;6&quot;&gt;&lt;/span&gt;6] &lt;a href=&quot;https://www.dimap.ufrn.br/~jmarcos/papers/AoT-McKinsey_Tarski.pdf&quot;&gt;https://www.dimap.ufrn.br/~jmarcos/papers/AoT-McKinsey_Tarski.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;7&quot;&gt;&lt;/span&gt;7] &lt;a href=&quot;https://logic.berkeley.edu/colloquium/BezhanishviliSlides.pdf&quot;&gt;https://logic.berkeley.edu/colloquium/BezhanishviliSlides.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;8&quot;&gt;&lt;/span&gt;8] &lt;a href=&quot;https://www2.math.uu.se/~palmgren/tillog/heyting3.pdf&quot;&gt;www2.math.uu.se/~palmgren/tillog/heyting3.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;9&quot;&gt;&lt;/span&gt;9] &lt;a href=&quot;http://festschriften.illc.uva.nl/j50/contribs/troelstra/troelstra.pdf&quot;&gt;http://festschriften.illc.uva.nl/j50/contribs/troelstra/troelstra.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;10&quot;&gt;&lt;/span&gt;10] &lt;a href=&quot;http://www.sciencedirect.com/science/article/pii/0022404980901024&quot;&gt;http://www.sciencedirect.com/science/article/pii/0022404980901024&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;11&quot;&gt;&lt;/span&gt;11] &lt;a href=&quot;https://arxiv.org/abs/1310.0263&quot;&gt;https://arxiv.org/abs/1310.0263&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;12&quot;&gt;&lt;/span&gt;12] &lt;a href=&quot;https://www.dpmms.cam.ac.uk/~martin/Research/Oldpapers/synthetic91.pdf&quot;&gt;https://www.dpmms.cam.ac.uk/~martin/Research/Oldpapers/synthetic91.pdf&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;13&quot;&gt;&lt;/span&gt;13] &lt;a href=&quot;http://www.brics.dk/RS/94/7/index.html&quot;&gt;http://www.brics.dk/RS/94/7/index.html&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;14&quot;&gt;&lt;/span&gt;14] &lt;a href=&quot;https://arxiv.org/abs/1710.10258&quot;&gt;https://arxiv.org/abs/1710.10258&lt;/a&gt;&lt;br&gt;
[&lt;span id=&quot;15&quot;&gt;&lt;/span&gt;15] &lt;a href=&quot;https://ncatlab.org/nlab/show/homotopy+hypothesis&quot;&gt;https://ncatlab.org/nlab/show/homotopy+hypothesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2018/computational-quadrinitarianism-curious-correspondences-go-cubical/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The State Comonad</title><link>https://comonad.com/reader/2018/the-state-comonad/</link><guid isPermaLink="false">https://comonad.com/reader/2018/the-state-comonad/</guid><pubDate>Sat, 06 Jan 2018 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 6 January 2018&lt;/p&gt;&lt;span id=&quot;more-1139&quot;&gt;&lt;/span&gt;&lt;p&gt;Is &lt;code&gt;State&lt;/code&gt; a &lt;code&gt;Comonad&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Not &lt;code&gt;Costate&lt;/code&gt; or rather, &lt;code&gt;Store&lt;/code&gt; as we tend to call it today, but actually &lt;code&gt;State s&lt;/code&gt; itself?&lt;/p&gt;
&lt;p&gt;Let's see!&lt;/p&gt;
&lt;p&gt;Recently there was a &lt;a href=&quot;https://www.reddit.com/r/haskell/comments/7oav51/i_made_a_monad_that_i_havent_seen_before_and_i/&quot;&gt;post to reddit&lt;/a&gt; in which the author &lt;code&gt;King_of_the_Homeless&lt;/code&gt; suggested that he might have a &lt;code&gt;Monad&lt;/code&gt; for &lt;code&gt;Store&lt;/code&gt;. Moreover, it is one that is compatible with the existing &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;ComonadApply&lt;/code&gt; instances. My &lt;a href=&quot;https://www.reddit.com/r/haskell/comments/7oav51/i_made_a_monad_that_i_havent_seen_before_and_i/ds81x2a/&quot;&gt;knee-jerk reaction&lt;/a&gt; was to disbelieve the result, but I'm glad I stuck with playing with it over the last day or so.&lt;/p&gt;
&lt;p&gt;In a much older post, I showed how to use the &lt;code&gt;Co&lt;/code&gt; &lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;comonad-to-monad-transformer&lt;/a&gt; to convert &lt;code&gt;Store s&lt;/code&gt; into &lt;code&gt;State s&lt;/code&gt;, but this is a different beast, it is a monad directly on &lt;code&gt;Store s&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# language DeriveFunctor #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Semigroup

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt;&lt;/span&gt;
  { peek :: s -&amp;gt; a, pos :: s }
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f) s
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt;
 (&lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) =&amp;gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (const a) mempty
  &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; g t = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (\m -&amp;gt; f m (g m)) (mappend s t)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; s =&amp;gt;
 &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s &amp;lt; @&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; g t = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (\m -&amp;gt; f m (g m)) (s &amp;lt;&amp;gt; t)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt;
 (&lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) =&amp;gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = pure
  m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt;
    (\s -&amp;gt; peek (k (peek m s)) s)
    (pos m `mappend` pos (k (peek m mempty)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My apologies for the &lt;code&gt;Semigroup&lt;/code&gt; vs. &lt;code&gt;Monoid&lt;/code&gt;, noise, as I'm still using GHC 8.2 locally. This will get a bit cleaner in a couple of months.&lt;/p&gt;
&lt;p&gt;Also, &lt;code&gt;peek&lt;/code&gt; here is flipped relative to the version in &lt;code&gt;Control.Comonad.Store.Class&lt;/code&gt; so that I can use it directly as a field accessor.&lt;/p&gt;
&lt;p&gt;As I noted, at first I was hesitant to believe it could work, but then I realized I'd &lt;a href=&quot;https://hackage.haskell.org/package/streams-3.3/docs/Data-Stream-Infinite-Functional-Zipper.html&quot;&gt;already implemented&lt;/a&gt; something like this for a special case of Store, in the 'streams' library, which got me curious. Upon reflection, this feels like the usual Store comonad is using the ability to distribute &lt;code&gt;(-&amp;gt;) e&lt;/code&gt; out or &lt;code&gt;(,) e&lt;/code&gt; in using a &quot;comonoid&quot;, which is always present in Haskell, just like how the State monad does. But the type above seems to indicate we can go the opposite direction with a monoid.&lt;/p&gt;
&lt;p&gt;So, in the interest of exploring duality, let's see if we can build a comonad instance for `State s`!&lt;/p&gt;
&lt;p&gt;Writing down the definition for state:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt;&lt;/span&gt;
  { runState :: s -&amp;gt; (a, s) }
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (a, s)
  &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; mf &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; ma = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; mf s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (f, s') -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ma s' &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      (a, s'') -&amp;gt; (f a, s'')
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = pure
  &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (a, s') -&amp;gt; runState (k a) s'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given a monoid for out state, extraction is pretty obvious:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; s =&amp;gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract m = fst $ runState m mempty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But the first stab we might take at how to duplicate, doesn't work.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  duplicate m = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt;
   (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t)
   , s
   )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It passes the `extract . duplicate = id` law easily:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; (duplicate m)
= extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s mempty)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m t
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ runState m
= m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But fails the second law:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; extract (duplicate m)
= fmap extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (fst $ runState m (mappend s mempty), s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (evalState m s, s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;because it discards the changes in the state.&lt;/p&gt;
&lt;p&gt;But the &lt;code&gt;King_of_the_Homeless&lt;/code&gt;'s trick from that post (and the Store code above) can be modified to this case. All we need to do is ensure that we modify the output state 's' as if we'd performed the action unmolested by the inner monoidal state that we can't see.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  duplicate m = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt;
    ( &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t)
    , snd $ runState m s
    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; (duplicate m)
= extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), snd $ runState m s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend mempty t)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m t
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ runState m
= m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;just like before, but the inner extraction case now works out and performs the state modification as expected:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; extract (duplicate m)
= fmap extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), snd $ runState m s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (extract $ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \t -&amp;gt; runState m (mappend s t), snd $ runState m s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (fst $ runState m (mappend s mempty), snd $ runState m s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; (fst $ runState m s, snd $ runState m s)
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ \s -&amp;gt; runState m s
= &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; $ runState m
= m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is still kind of a weird beast as it performs the state action twice with different states, but it does pass at least the left and right unit laws.&lt;/p&gt;
&lt;p&gt;Some questions:&lt;/p&gt;
&lt;p&gt;1. Proving associativity is left as an exercise. It passes visual inspection and my gut feeling, but I haven't bothered to do all the plumbing to check it out. I've been wrong enough before, it'd be nice to check!&lt;/p&gt;
&lt;p&gt;[Edit: Simon Marechal (bartavelle) has a &lt;a href=&quot;http://lpaste.net/361413&quot;&gt;coq proof&lt;/a&gt; of the associativity and other axioms.]&lt;/p&gt;
&lt;p&gt;2. Does this pass the &lt;code&gt;ComonadApply&lt;/code&gt; laws?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt; @&amp;gt;) = (&amp;lt; *&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[Edit: &lt;a href=&quot;https://www.reddit.com/r/haskell/comments/7ojy6x/the_comonadreader_the_state_comonad/dsabeij/&quot;&gt;No&lt;/a&gt;.]&lt;/p&gt;
&lt;p&gt;3. The streams code above suggests at least one kind of use-case, something like merging together changes of position in a stream, analogous to the &quot;zipping monad&quot; you have on infinite streams. But now the positions aren't just Integers, they are arbitrary values taken from any monoid you want. What other kind of spaces might we want to &quot;zip&quot; in this manner?&lt;/p&gt;
&lt;p&gt;4. Is there an analogous construction possible for an &lt;a href=&quot;https://comonad.com/reader/2015/heap-of-successes/#update-vs--state&quot;&gt;&quot;update monad&quot;&lt;/a&gt; or &quot;coupdate comonad&quot;? Does it require a monoid that acts on a monoid rather than arbitrary state like the &lt;a href=&quot;https://www.youtube.com/watch?v=Txf7swrcLYs&quot;&gt;semi-direct product of monoids&lt;/a&gt; or a &lt;a href=&quot;https://www.cse.iitk.ac.in/users/ppk/research/publication/Conference/2016-09-22-How-to-twist-pointers.pdf&quot;&gt;&quot;twisted functor&quot;&lt;/a&gt;? Is the result if it exists a twisted functor?&lt;/p&gt;
&lt;p&gt;5. Does `Co` translate from this comonad to the monad on `Store`?&lt;/p&gt;
&lt;p&gt;6. Is there a (co)monad transformer version of these?&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://gist.github.com/ekmett/1d8029a19546278adab92ebd3057f4b2&quot;&gt;Gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2018/the-state-comonad/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Walk-through of Computational Reflection in Coq</title><link>https://comonad.com/reader/talks/youtube-4BmvEInzoY0/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-4BmvEInzoY0/</guid><pubDate>Wed, 15 Nov 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Gregory Malecha · 15 November 2017&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;4BmvEInzoY0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4BmvEInzoY0&quot;&gt;Watch on YouTube&lt;/a&gt; · 74 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;November Boston Haskell Meetup @ ThoughBot&lt;/p&gt;
&lt;p&gt;Gregory Malecha presents techniques for computational reflection in the Coq proof assistant. Computational reflection is a proof technique that makes use of programs written within the language of the proof assistant itself, rather than a meta-language.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/Boston-Haskell/events/244608020/&quot;&gt;https://www.meetup.com/Boston-Haskell/events/244608020/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-4BmvEInzoY0/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monoidal Parsing</title><link>https://comonad.com/reader/talks/youtube-090hIEiUoE0/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-090hIEiUoE0/</guid><pubDate>Wed, 18 Oct 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 October 2017&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;090hIEiUoE0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=090hIEiUoE0&quot;&gt;Watch on YouTube&lt;/a&gt; · 92 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;October Boston Haskell Meetup @ ThoughBot&lt;/p&gt;
&lt;p&gt;Well known Haskell guru Edward Kmett speaking about parsing programs (with Haskell-like syntax) in parallel and incrementally by making some small changes to the grammar. Talk provides a nice whirlwind tour of semigroup actions, inverse semigroups and a bunch of less well-known bits of algebra that have a lot of applications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/Boston-Haskell/events/244136649/&quot;&gt;https://www.meetup.com/Boston-Haskell/events/244136649/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-090hIEiUoE0/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Algebraic Databases</title><link>https://comonad.com/reader/talks/youtube-JzShJfikr4g/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-JzShJfikr4g/</guid><pubDate>Wed, 20 Sep 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Ryan Wisnesky · 20 September 2017&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;JzShJfikr4g&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JzShJfikr4g&quot;&gt;Watch on YouTube&lt;/a&gt; · 86 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Ryan Wisnesky presents Algebraic Databases.&lt;/p&gt;
&lt;p&gt;See meetup for full details:&lt;br&gt;
&lt;a href=&quot;https://www.meetup.com/Boston-Haskell/events/243375233/&quot;&gt;https://www.meetup.com/Boston-Haskell/events/243375233/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-JzShJfikr4g/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Introduction to Cryptocurrencies in Haskell</title><link>https://comonad.com/reader/talks/youtube-wjyiOXRuUdo/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-wjyiOXRuUdo/</guid><pubDate>Tue, 05 Sep 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Thomas Dietert · 5 September 2017 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;wjyiOXRuUdo&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wjyiOXRuUdo&quot;&gt;Watch on YouTube&lt;/a&gt; · 100 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Thomas Dietert gives an overview of various topics underlying cryptocurrencies and demonstrates his personal cryptocurrency, nanocoin, written in Haskell.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-wjyiOXRuUdo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SMT for DSLs: a Tutorial</title><link>https://comonad.com/reader/talks/youtube-2rhrxkNtrM4/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-2rhrxkNtrM4/</guid><pubDate>Sun, 06 Aug 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Cody Roux · 6 August 2017 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;2rhrxkNtrM4&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=2rhrxkNtrM4&quot;&gt;Watch on YouTube&lt;/a&gt; · 112 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Cody Roux gives an overview of the sbv library for interacting with SMT solvers in Haskell, and gives strategies for using it to verify properties of/in domain specific languages.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-2rhrxkNtrM4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cracking Multi-Language Transformations</title><link>https://comonad.com/reader/talks/youtube-SmBpQ3V9Yqo/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-SmBpQ3V9Yqo/</guid><category>Talk</category><description>&lt;p&gt;James Koppel · July 2017 · day unknown&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;SmBpQ3V9Yqo&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SmBpQ3V9Yqo&quot;&gt;Watch on YouTube&lt;/a&gt; · 69 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Jimmy Koppel explains his work on performing rewriting transforms in ways that are language agnostic and produce more human readable code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-SmBpQ3V9Yqo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Efficiently coding for modern CPUs</title><link>https://comonad.com/reader/talks/efficient-modern-cpus-zurihac-2017/</link><guid isPermaLink="false">https://comonad.com/reader/talks/efficient-modern-cpus-zurihac-2017/</guid><pubDate>Sun, 11 Jun 2017 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 11 June 2017&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;KzqNQMpRbac&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KzqNQMpRbac&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Efficiently coding for modern CPUs — ZuriHac 2017.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KzqNQMpRbac&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/efficient-modern-cpus-zurihac-2017/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>VR: Test Framework</title><link>https://comonad.com/reader/talks/vr-test-framework-2016/</link><guid isPermaLink="false">https://comonad.com/reader/talks/vr-test-framework-2016/</guid><pubDate>Wed, 14 Sep 2016 12:00:00 GMT</pubDate><category>Demo</category><description>&lt;p&gt;Edward Kmett · 14 September 2016 · published&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;pBjzyi3YVVA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=pBjzyi3YVVA&quot;&gt;Watch on YouTube&lt;/a&gt; · 1 minute&lt;/figcaption&gt;&lt;/figure&gt;&lt;p class=&quot;editorial&quot;&gt;A development snapshot of the VR engine. The source project is linked below.&lt;/p&gt;&lt;p&gt;Just a work in progress shot of my current VR engine&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/vr-test-framework-2016/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Desugaring Haskell’s do-Notation into Applicative Operations</title><link>https://comonad.com/reader/papers/applicative-do/</link><guid isPermaLink="false">https://comonad.com/reader/papers/applicative-do/</guid><category>Paper</category><description>&lt;p&gt;Simon Marlow, Simon Peyton Jones, Edward Kmett, Andrey Mokhov · September 2016 · day unknown&lt;/p&gt;&lt;p&gt;An algorithm for translating Haskell’s do-notation into applicative operations where possible, retaining monadic dependencies where necessary. The paper describes the design, implementation, and applications of ApplicativeDo.&lt;/p&gt;&lt;p&gt;&lt;a class=&quot;document-download&quot; href=&quot;https://comonad.com/assets/documents/applicative-do.pdf&quot;&gt;Read the paper (PDF · 13 pages)&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/documents/applicative-do.pdf&quot; download=&quot;&quot;&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/papers/applicative-do/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monad Transformer Lenses</title><link>https://comonad.com/reader/talks/monad-transformer-lenses-warsaw-2016/</link><guid isPermaLink="false">https://comonad.com/reader/talks/monad-transformer-lenses-warsaw-2016/</guid><pubDate>Mon, 25 Jul 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 25 July 2016 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Bxcz23GOJqc&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Bxcz23GOJqc&quot;&gt;Watch on YouTube&lt;/a&gt; · 84 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I'll talk a bit about how we can do lenses in much more general settings. Then, given that the venue is &quot;Monadic Warsaw&quot; I'll show how we can build a monoidal category of monad transformers and work with lenses on this category with an eye towards how this can let us produce much more efficient code than we can with just the MTL classes as we know them today.&lt;br&gt;
No real prior exposure to lenses is required, and all talk of profunctors and the like should be self-contained, but some basic understanding of monad transformers would be helpful.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/monad-transformer-lenses-warsaw-2016/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monad Homomorphisms</title><link>https://comonad.com/reader/talks/monad-homomorphisms-zurihac-2016/</link><guid isPermaLink="false">https://comonad.com/reader/talks/monad-homomorphisms-zurihac-2016/</guid><pubDate>Sat, 23 Jul 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 23 July 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;YTaNkWjd-ac&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YTaNkWjd-ac&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Monad Homomorphisms — ZuriHac 2016.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YTaNkWjd-ac&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/monad-homomorphisms-zurihac-2016/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>First-class implementations</title><link>https://comonad.com/reader/talks/youtube-heU8NyX5Hus/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-heU8NyX5Hus/</guid><pubDate>Wed, 18 May 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;François-René Rideau · 18 May 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;heU8NyX5Hus&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=heU8NyX5Hus&quot;&gt;Watch on YouTube&lt;/a&gt; · 68 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Faré Rideau's talk at Boston Haskell, May 18, 2016&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://fare.tunes.org/files/cs/fci-bh2016.pdf&quot;&gt;slides&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-heU8NyX5Hus/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>binary-serialize-cbor</title><link>https://comonad.com/reader/talks/youtube-Mj2cXQXgyWE/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-Mj2cXQXgyWE/</guid><pubDate>Wed, 20 Apr 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Austin Seipp · 20 April 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Mj2cXQXgyWE&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Mj2cXQXgyWE&quot;&gt;Watch on YouTube&lt;/a&gt; · 56 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Austin's talk at the Boston Haskell Meetup - April 20, 2016&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-Mj2cXQXgyWE/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Probabilistic Programming Live-code</title><link>https://comonad.com/reader/talks/youtube-8YUUuZMawdY/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-8YUUuZMawdY/</guid><pubDate>Wed, 20 Apr 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Alexey Radul · 20 April 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;8YUUuZMawdY&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8YUUuZMawdY&quot;&gt;Watch on YouTube&lt;/a&gt; · 70 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Alexey's talk for the Boston Haskell Meetup - April 20, 2016&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-8YUUuZMawdY/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Composing (Music) in Haskell</title><link>https://comonad.com/reader/talks/youtube-Jmw6LLNQQfs/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-Jmw6LLNQQfs/</guid><pubDate>Mon, 28 Mar 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Stuart Popejoy · 28 March 2016 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Jmw6LLNQQfs&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Jmw6LLNQQfs&quot;&gt;Watch on YouTube&lt;/a&gt; · 57 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Stuart Popejoy's talk on music composition for the Boston Haskell meetup group.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-Jmw6LLNQQfs/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Haskell, Startups, and Domain Specific Languages</title><link>https://comonad.com/reader/talks/youtube-R4nLSxCKkNw/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-R4nLSxCKkNw/</guid><pubDate>Wed, 16 Mar 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Adam Wespiser · 16 March 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;R4nLSxCKkNw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=R4nLSxCKkNw&quot;&gt;Watch on YouTube&lt;/a&gt; · 36 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Adam Wespiser's talk for the Boston Haskell meetup group, March 16 2016&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-R4nLSxCKkNw/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Haskell Code Review!</title><link>https://comonad.com/reader/talks/youtube-0fyrf83pjMg/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-0fyrf83pjMg/</guid><pubDate>Sun, 28 Feb 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;James Larisch · 28 February 2016 · uploaded&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;0fyrf83pjMg&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0fyrf83pjMg&quot;&gt;Watch on YouTube&lt;/a&gt; · 60 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;James Larisch presents his Haskell learning project for review by the Boston Haskell meetup peanut gallery&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-0fyrf83pjMg/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Undecidable Superclasses</title><link>https://comonad.com/reader/talks/youtube-ZL9ehIJhk98/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-ZL9ehIJhk98/</guid><pubDate>Wed, 17 Feb 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 17 February 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;ZL9ehIJhk98&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZL9ehIJhk98&quot;&gt;Watch on YouTube&lt;/a&gt; · 36 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Edward shows the Boston Haskell meetup group some of his GHC 8.0 toys.  2016.02.17&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-ZL9ehIJhk98/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Dimensional</title><link>https://comonad.com/reader/talks/youtube--Kz7SYZNoUU/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube--Kz7SYZNoUU/</guid><pubDate>Wed, 20 Jan 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Douglas McClean · 20 January 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;-Kz7SYZNoUU&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-Kz7SYZNoUU&quot;&gt;Watch on YouTube&lt;/a&gt; · 20 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Boston Haskell Meetup, January 20 2016&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube--Kz7SYZNoUU/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>On Reflex</title><link>https://comonad.com/reader/talks/youtube-MfXxuy_CJSk/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-MfXxuy_CJSk/</guid><pubDate>Wed, 20 Jan 2016 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Greg Hale · 20 January 2016&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;MfXxuy_CJSk&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MfXxuy_CJSk&quot;&gt;Watch on YouTube&lt;/a&gt; · 11 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Greg Hale's reflex-dom lightning talk for &lt;a href=&quot;http://www.meetup.com/Boston-Haskell/&quot;&gt;http://www.meetup.com/Boston-Haskell/&lt;/a&gt; on Jan 20, 2016.&lt;br&gt;
try-reflex: &lt;a href=&quot;https://github.com/ryantrinkle/try-reflex&quot;&gt;https://github.com/ryantrinkle/try-reflex&lt;/a&gt;&lt;br&gt;
reflex-dom-contrib: &lt;a href=&quot;https://github.com/reflex-frp/reflex-dom-contrib&quot;&gt;https://github.com/reflex-frp/reflex-dom-contrib&lt;/a&gt;&lt;br&gt;
my-reflex-recipes: &lt;a href=&quot;http://web.mit.edu/greghale/Public/my-reflex-recipes/&quot;&gt;http://web.mit.edu/greghale/Public/my-reflex-recipes/&lt;/a&gt;&lt;br&gt;
cochleagram: &lt;a href=&quot;https://cbmm.github.io/cochleagram&quot;&gt;https://cbmm.github.io/cochleagram&lt;/a&gt; (Chrome only)&lt;br&gt;
cochleagram code: &lt;a href=&quot;http://github.com/cbmm/cochleagram&quot;&gt;http://github.com/cbmm/cochleagram&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-MfXxuy_CJSk/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Adjoint Triples</title><link>https://comonad.com/reader/2016/adjoint-triples/</link><guid isPermaLink="false">https://comonad.com/reader/2016/adjoint-triples/</guid><pubDate>Wed, 13 Jan 2016 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 13 January 2016&lt;/p&gt;&lt;p&gt;A common occurrence in category theory is the &lt;a href=&quot;https://ncatlab.org/nlab/show/adjoint+triple&quot;&gt;adjoint triple&lt;/a&gt;. This is a pair of adjunctions relating three functors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;H&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;H&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perhaps part of the reason they are so common is that (co)limits form one:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;colim&lt;/span&gt; ⊣ Δ ⊣ lim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;Δ : C -&amp;gt; C^J&lt;/code&gt; is the diagonal functor, which takes objects in &lt;code&gt;C&lt;/code&gt; to the constant functor returning that object. A version of this shows up in Haskell (with some extensions) and dependent type theories, as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;∃ ⊣ &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; ⊣ ∀
Σ ⊣ &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; ⊣ Π
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where, if we only care about quantifying over a single variable, existential and sigma types can be seen as a left adjoint to a diagonal functor that maps types into constant type families (either over &lt;code&gt;*&lt;/code&gt; for the first triple in Haskell, or some other type for the second in a dependently typed language), while universal and pi types can be seen as a right adjoint to the same.&lt;/p&gt;
&lt;p&gt;It's not uncommon to see the above information in type theory discussion forums. But, there are a few cute properties and examples of adjoint triples that I haven't really seen come up in such contexts.&lt;/p&gt;
&lt;p&gt;To begin, we can compose the two adjunctions involved, since the common functor ensures things match up. By calculating on the hom definition, we can see:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;FGA&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt;)     &lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;GFA&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt;)
    ~=              ~=
&lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;GA&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;GB&lt;/span&gt;)     &lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;FA&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;HB&lt;/span&gt;)
    ~=              ~=
&lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;HGB&lt;/span&gt;)     &lt;span class=&quot;hljs-type&quot;&gt;Hom&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;GHB&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there are two ways to compose the adjunctions, giving two induced adjunctions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;FG&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;HG&lt;/span&gt;,  &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;GH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there is something special about these adjunctions. Note that &lt;code&gt;FG&lt;/code&gt; is the comonad for the &lt;code&gt;F ⊣ G&lt;/code&gt; adjunction, while &lt;code&gt;HG&lt;/code&gt; is the monad for the &lt;code&gt;G ⊣ H&lt;/code&gt; adjunction. Similarly, &lt;code&gt;GF&lt;/code&gt; is the &lt;code&gt;F ⊣ G&lt;/code&gt; monad, and &lt;code&gt;GH&lt;/code&gt; is the &lt;code&gt;G ⊣ H&lt;/code&gt; comonad. So each adjoint triple gives rise to two adjunctions between monads and comonads.&lt;/p&gt;
&lt;p&gt;The second of these has another interesting property. We often want to consider the algebras of a monad, and coalgebras of a comonad. The (co)algebra operations with carrier &lt;code&gt;A&lt;/code&gt; have type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;alg&lt;/span&gt;   : &lt;span class=&quot;hljs-type&quot;&gt;GFA&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;coalg&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GHA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but these types are isomorphic according to the &lt;code&gt;GF ⊣ GH&lt;/code&gt; adjunction. Thus, one might guess that &lt;code&gt;GF&lt;/code&gt; monad algebras are also &lt;code&gt;GH&lt;/code&gt; comonad coalgebras, and that in such a situation, we actually have some structure that can be characterized both ways. In fact this is true for any monad left adjoint to a comonad; &lt;a href=&quot;https://comonad.com/reader/2016/adjoint-triples/#note0&quot;&gt;[0]&lt;/a&gt; but all adjoint triples give rise to these.&lt;/p&gt;
&lt;p&gt;The first adjunction actually turns out to be more familiar for the triple examples above, though. (Edit: &lt;a href=&quot;https://comonad.com/reader/2016/adjoint-triples/#note2&quot;&gt;[2]&lt;/a&gt;) If we consider the &lt;code&gt;Σ ⊣ Const ⊣ Π&lt;/code&gt; adjunction, where:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;Σ Π : (&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;Σ&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt;
Σ&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; × &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt;
Π&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt;
Π&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So this is the familiar adjunction:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; × - ⊣ &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; -&amp;gt; -
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, there happens to be a triple that is a bit more interesting for both cases. It refers back to categories of functors vs. bare type constructors mentioned in previous posts. So, suppose we have a category called &lt;code&gt;Con&lt;/code&gt; whose objects are (partially applied) type constructors (f, g) with kind &lt;code&gt;* -&amp;gt; *&lt;/code&gt;, and arrows are polymorphic functions with types like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; g x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And let us further imagine that there is a similar category, called &lt;code&gt;Func&lt;/code&gt;, except its objects are the things with &lt;code&gt;Functor&lt;/code&gt; instances. Now, there is a functor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;U&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Func&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Con&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;that 'forgets' the functor instance requirement. This functor is in the middle of an adjoint triple:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;U&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Con&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Func&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;F&lt;/code&gt; creates the free functor over a type constructor, and &lt;code&gt;C&lt;/code&gt; creates the cofree functor over a type constructor. These can be written using the types:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a = forall e. &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; f r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and these types will also serve as the types involved in the composite adjunctions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;FU&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;CU&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Func&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Func&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;UF&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;UC&lt;/span&gt; : &lt;span class=&quot;hljs-type&quot;&gt;Con&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Con&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;CU&lt;/code&gt; is a monad on functors, and the Yoneda lemma tells us that it is actually the identity monad. Similarly, &lt;code&gt;FU&lt;/code&gt; is a comonad, and the co-Yoneda lemma tells us that it is the identity comonad (which makes sense, because identity is self-adjoint; and the above is why &lt;code&gt;F&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; are often named &lt;code&gt;(Co)Yoneda&lt;/code&gt; in Haskell examples).&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;code&gt;UF&lt;/code&gt; is a &lt;em&gt;monad&lt;/em&gt; on type constructors (note, &lt;code&gt;U&lt;/code&gt; isn't represented in the Haskell types; &lt;code&gt;F&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; just play triple duty, and the constraints on &lt;code&gt;f&lt;/code&gt; control what's going on):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;eta&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;eta&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; id

&lt;span class=&quot;hljs-title&quot;&gt;transform&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; g x) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;transform&lt;/span&gt; tr (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; g x) = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; g (tr x)

&lt;span class=&quot;hljs-title&quot;&gt;mu&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;mu&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; g (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; h x)) = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (g . h) x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and &lt;code&gt;UC&lt;/code&gt; is a &lt;em&gt;comonad&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;epsilon&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;epsilon&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; e) = e id

&lt;span class=&quot;hljs-title&quot;&gt;transform'&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; g x) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;transform'&lt;/span&gt; tr (&lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; (tr . e)

&lt;span class=&quot;hljs-title&quot;&gt;delta&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; f) a
&lt;span class=&quot;hljs-title&quot;&gt;delta&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; $ \h -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; $ \g -&amp;gt; e (g . h)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are not the identity (co)monad, but this is the case where we have algebras and coalgebras that are equivalent. So, what are the (co)algebras? If we consider &lt;code&gt;UF&lt;/code&gt; (and unpack the definitions somewhat):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;alg&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; e. (e -&amp;gt; a, f e) -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;alg&lt;/span&gt; (id, x) = x
&lt;span class=&quot;hljs-title&quot;&gt;alg&lt;/span&gt; (g . h, x) = alg (g, alg (h, x))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and for &lt;code&gt;UC&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;coalg&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; r) -&amp;gt; f r
&lt;span class=&quot;hljs-title&quot;&gt;coalg&lt;/span&gt; x id = x
&lt;span class=&quot;hljs-title&quot;&gt;coalg&lt;/span&gt; x (g . h) = coalg (coalg x h) g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in other words, (co)algebra actions of these (co)monads are (mangled) &lt;code&gt;fmap&lt;/code&gt; implementations, and the commutativity requirements are exactly what is required to be a law abiding instance. So the (co)algebras are exactly the &lt;code&gt;Functors&lt;/code&gt;. &lt;a href=&quot;https://comonad.com/reader/2016/adjoint-triples/#note1&quot;&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are, of course, many other examples of adjoint triples. And further, there are even adjoint quadruples, which in turn give rise to adjoint triples of (co)monads. Hopefully this has sparked some folks' interest in finding and studying more interesting examples.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;note0&quot;&gt;&lt;/span&gt;[0]: Another exmaple is &lt;code&gt;A × - ⊣ A -&amp;gt; -&lt;/code&gt; where the &lt;code&gt;A&lt;/code&gt; in question is a monoid. (Co)monad (co)algebras of these correspond to actions of the monoid on the carrier set.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;note1&quot;&gt;&lt;/span&gt;[1]: This shouldn't be too surprising, because having a category of (co)algebraic structures that is equivalent to the category of (co)algebras of the (co)monad that comes from the (co)free-forgetful adjunction is the basis for doing algebra in category theory (with (co)monads, at least). However, it is somewhat unusual for a forgetful functor to have both a left and right adjoint. In many cases, something is either algebraic or coalgebraic, and not both.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;note2&quot;&gt;&lt;/span&gt;[2]: Urs Schreiber informed me of an interesting interpretation of the &lt;code&gt;ConstΣ ⊣ ConstΠ&lt;/code&gt; adjunction. If you are familiar with modal logic and the possible worlds semantics thereof, you can probably imagine that we could model it using something like &lt;code&gt;P : W -&amp;gt; Type&lt;/code&gt;, where &lt;code&gt;W&lt;/code&gt; is the type of possible worlds, and propositions are types. Then values of type &lt;code&gt;Σ P&lt;/code&gt; demonstrate that &lt;code&gt;P&lt;/code&gt; holds in particular worlds, while values of type &lt;code&gt;Π P&lt;/code&gt; demonstrate that it holds in all worlds. &lt;code&gt;Const&lt;/code&gt; turns these types back into world-indexed 'propositions,' so &lt;code&gt;ConstΣ&lt;/code&gt; is the possibility modality and &lt;code&gt;ConstΠ&lt;/code&gt; is the necessity modality.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2016/adjoint-triples/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Bound</title><link>https://comonad.com/reader/2015/bound/</link><guid isPermaLink="false">https://comonad.com/reader/2015/bound/</guid><pubDate>Wed, 02 Dec 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 2 December 2015&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; provides a powerful but simple toolbox for dealing with capture-avoiding substitution in your code. It lets you use classes you already know: &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;Foldable&lt;/code&gt; and &lt;code&gt;Traversable&lt;/code&gt; to manipulate your syntax tree, and it factors out issues of name capture into a reusable monad transformer named &lt;code&gt;Scope&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What I want to do today is help motivate the design of the &lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; library by talking a bit about alternatives. This may serve, with a few digressions, as a bit of a crash course on capture-avoiding substitution, for those who don't deal with this issue on a day-to-day basis. This presentation is based on a talk I gave on &lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt;, but it has been upgraded to work with the School of Haskell tools for easier online consumption. In particular, I've tried to make the code fragments executable, and greatly expand on the content to cover things in greater depth. The &lt;a href=&quot;http://www.slideshare.net/ekmett/bound-making-de-bruijn-succ-less&quot;&gt;original slides&lt;/a&gt; are also available, but were designed with me speaking over them in mind.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-a-name&quot;&gt;What is in a Name?&lt;/h2&gt;
&lt;p&gt;We use names in lots of contexts, but any program that deals with names has to deal with a number of issues such as capture avoidance and deciding alpha equivalance... and others that will come up as we go.&lt;/p&gt;
&lt;p&gt;If you go to write a syntax tree, the dumbest thing that can possibly work would be something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  print $ &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt;
  print $ &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt;)
  print $ &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two problems we want to address in almost any syntax tree are:&lt;/p&gt;
&lt;p&gt;1.) Capture Avoidance&lt;/p&gt;
&lt;p&gt;Blindly substituting&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;z&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;for &lt;code&gt;z&lt;/code&gt; would yield&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which now causes the formerly free variable &lt;code&gt;y&lt;/code&gt; to now reference the &lt;code&gt;y&lt;/code&gt; bound by the outer lambda.&lt;/p&gt;
&lt;p&gt;2.) Alpha Equivalence&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;both mean the same thing and it'd be nice to be able to check this easily, make them hash the
same for common sub-expression elimination, etc.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/bound/#binding-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is a cottage industry of solutions to the naming problem:&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Naïve substitution&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Calculus-Semantics-Studies-Foundations-Mathematics/dp/0444875085&quot;&gt;The Barendregt convention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Higher-order_abstract_syntax&quot;&gt;HOAS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Weak HOAS/&lt;a href=&quot;http://adam.chlipala.net/papers/PhoasICFP08/&quot;&gt;PHOAS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cs.ru.nl/~james/RESEARCH/haskell2004.pdf&quot;&gt;&quot;I am not a Number: I am a Free Variable!&quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chargueraud.org/research/2009/ln/main.pdf&quot;&gt;The Locally Nameless Representation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hackage.haskell.org/package/unbound&quot;&gt;Unbound&lt;/a&gt;, which mixes Barendregt with Locally Nameless&lt;/li&gt;
&lt;li&gt;Locally Nameless Syntax with De Bruijn Indices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm not looking to address all of these here, just a few, to showcase issues with the different points in the design space, and then to try to offer up a nice point in the design space (&lt;code&gt;bound&lt;/code&gt;) that combines many of the advantages with few of the disadvantages.&lt;/p&gt;
&lt;h3 id=&quot;na-ve-substitution&quot;&gt;Naïve Substitution&lt;/h3&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) The syntax trees are pretty and easy to read.&lt;/p&gt;
&lt;p&gt;2.) Easy to use to get started&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) It is easy even for experts to make mistakes.&lt;/p&gt;
&lt;p&gt;2.) Alpha equivalence checking is tedious&lt;/p&gt;
&lt;p&gt;3.) It is comically slow.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List (&lt;span class=&quot;hljs-title&quot;&gt;union&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;span&lt;/span&gt;, (\\))

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)


&lt;span class=&quot;hljs-title&quot;&gt;freeVars&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;]
&lt;span class=&quot;hljs-title&quot;&gt;freeVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; x) = [x]
&lt;span class=&quot;hljs-title&quot;&gt;freeVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) = freeVars a `union` freeVars b
&lt;span class=&quot;hljs-title&quot;&gt;freeVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; n x) = freeVars x \\ [n]

&lt;span class=&quot;hljs-title&quot;&gt;allVars&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;]
&lt;span class=&quot;hljs-title&quot;&gt;allVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; x) = [x]
&lt;span class=&quot;hljs-title&quot;&gt;allVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) = allVars a `union` allVars b
&lt;span class=&quot;hljs-title&quot;&gt;allVars&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; n x) = allVars x

&lt;span class=&quot;hljs-title&quot;&gt;subst&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;subst&lt;/span&gt; x s b = sub vs0 b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  sub _ e@(&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; v)
    | v == x = s
    | otherwise = e
  sub vs e@(&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; v e')
    | v == x = e
    | v `elem` fvs = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; v' (sub (v':vs) e'')
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; v (sub vs e') &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    v' = newId vs
    e'' = subst v (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; v') e'
  sub vs (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a) = sub vs f `&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;` sub vs a
  fvs = freeVars s
  vs0 = fvs `union` allVars b

&lt;span class=&quot;hljs-title&quot;&gt;newId&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;newId&lt;/span&gt; vs = head (names \\ vs)

&lt;span class=&quot;hljs-title&quot;&gt;names&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;]
&lt;span class=&quot;hljs-title&quot;&gt;names&lt;/span&gt; = [ [i] | i &amp;lt;- [&lt;span class=&quot;hljs-string&quot;&gt;'a'&lt;/span&gt;..&lt;span class=&quot;hljs-string&quot;&gt;'z'&lt;/span&gt;]] ++ [i : show j | j &amp;lt;- [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..], i &amp;lt;- [&lt;span class=&quot;hljs-string&quot;&gt;'a'&lt;/span&gt;..&lt;span class=&quot;hljs-string&quot;&gt;'z'&lt;/span&gt;] ]

&lt;span class=&quot;hljs-comment&quot;&gt;-- show and we can see that this deals with capture avoidance&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ subst &lt;span class=&quot;hljs-string&quot;&gt;&quot;z&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;x&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt;)) (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;y&quot;&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;z&quot;&lt;/span&gt;))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code is adapted from Lennart Augustsson's excellent &lt;a href=&quot;http://www.augustsson.net/Darcs/Lambda/top.pdf&quot;&gt;λ-calculus cooked four ways&lt;/a&gt;, which provides a nice crash course on name binding for evaluation.&lt;/p&gt;
&lt;p&gt;[Edited &lt;em&gt;August 27 2013&lt;/em&gt;: The code fragment above was updated based on a conversation with Marc André Ziegert to deal with an issue where in the &lt;code&gt;v &lt;code&gt;elem&lt;/code&gt; fvs&lt;/code&gt; case under &lt;code&gt;sub&lt;/code&gt; it wasn't properly updating the set of &lt;code&gt;allVars b&lt;/code&gt; when it introduced &lt;code&gt;v'&lt;/code&gt; into scope. I told you naïve substitution was tricky!]&lt;/p&gt;
&lt;h3 id=&quot;the-barendregt-convention&quot;&gt;The Barendregt Convention&lt;/h3&gt;
&lt;p&gt;This one is a serious contender. It is what GHC uses.&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) The &lt;a href=&quot;http://research.microsoft.com/en-us/um/people/simonpj/Papers/inlining/&quot;&gt;Secrets of the Glasgow Haskell Compiler inliner&lt;/a&gt; paper by &lt;a href=&quot;http://www.youtube.com/watch?v=IDhz_mVcVCQ&quot;&gt;Simon and Simon&lt;/a&gt; describes a technique they call &quot;the Rapier,&quot; which can make this really fast.&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) Easy even for experts to screw up.&lt;/p&gt;
&lt;p&gt;2.) Alpha equivalence is still tedious.&lt;/p&gt;
&lt;p&gt;3.) Need a globally unique variable supply. e.g. &lt;a href=&quot;https://hackage.haskell.org/package/concurrent-supply&quot;&gt;concurrent-supply&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.) The obvious implementation technique chews through a scarily large number of variable IDs! Without the Rapier there is a lot of &quot;administrative&quot; renaming going on.&lt;/p&gt;
&lt;h3 id=&quot;higher-order-abstract-syntax-hoas&quot;&gt;Higher-Order Abstract Syntax (HOAS)&lt;/h3&gt;
&lt;p&gt;HOAS cheats and borrows substitution from the host language.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, but a Show instance here is hard!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) It provides ridiculously fast substitution by comparison to other techniques.&lt;/p&gt;
&lt;p&gt;2.) Meijer and Hutton's &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.64.4921&amp;rep=rep1&amp;type=pdf&quot;&gt;&quot;Bananas in Space&quot;&lt;/a&gt;, Fegaras and Sheard's &lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.2763&quot;&gt;&quot;Revisiting Catamorphisms over Datatypes with Embedded Functions (or, Programs from Outer Space)&lt;/a&gt; and Weirich and Washburn's &lt;a href=&quot;http://www.seas.upenn.edu/~sweirich/papers/itabox/icfp-published-version.pdf&quot;&gt;&quot;Boxes Go Bananas: Encoding Higher-order Abstract Syntax with Parametric Polymorphism&quot;&lt;/a&gt; each describe forms of catamorphism that can be used on these to work under binders.&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) It doesn't work in theorem provers like Coq or Agda, because &lt;code&gt;Exp&lt;/code&gt; occurs in both positive and negative position, causing it to fail the positivity check.&lt;/p&gt;
&lt;p&gt;2.) It is quite hard to work under binders. You often have to invert your control flow for passes and think &quot;inside out.&quot;&lt;/p&gt;
&lt;p&gt;3.) You have to deal with exotic terms that do bad things like inspect the expression they are given, so it is in some sense &quot;too big.&quot;&lt;/p&gt;
&lt;p&gt;4.) Alpha equivalence is still tedious.&lt;/p&gt;
&lt;p&gt;5.) In &lt;a href=&quot;https://comonad.com/reader/2008/rotten-bananas/&quot;&gt;&quot;Rotten Bananas&quot;&lt;/a&gt; on &lt;a href=&quot;http://comonad.com/&quot;&gt;comonad.com&lt;/a&gt; I go through the issues with general recursion in this approach.&lt;/p&gt;
&lt;p&gt;Variants such as Weak HOAS/&lt;a href=&quot;http://adam.chlipala.net/papers/PhoasICFP08/&quot;&gt;PHOAS&lt;/a&gt;/&lt;a href=&quot;http://www.seas.upenn.edu/~sweirich/papers/itabox/icfp-published-version.pdf&quot;&gt;Weirich and Washburn&lt;/a&gt; exist to address some of these issues (e.g. working in Coq/Agda, restoring positivity, ruling out exotic terms) at the expense of other problems (e.g. losing the notion of catamorphism or general recursion).&lt;/p&gt;
&lt;h3 id=&quot;de-bruijn-indices&quot;&gt;De Bruijn Indices&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;M'colleague Bob Atkey once memorably described the capacity to put up with De Bruijn indices as a Cylon
detector, the kind of reverse Turing Test that the humans in Battlestar Galactica invent, the better to
recognize one another by their common inadequacies. He had a point&lt;/p&gt;
&lt;p&gt;&lt;em&gt;-Conor McBride, &quot;I am not a number, I am a classy hack&quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can split variables into bound and free:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, but it is boring.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could define combinators to bind names and instantiate them&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but let's adopt Conor McBride's less error prone convention instead:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)

  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, and is even slightly interesting.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With Conor's convention, &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; actually have useful types that prevent you from doing bad things. Renaming &lt;code&gt;Bound&lt;/code&gt; to &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;Free&lt;/code&gt; to &lt;code&gt;F&lt;/code&gt;, then adapting the approach he takes in his excellent functional pearl with James McKinna &lt;a href=&quot;http://www.cs.ru.nl/~james/RESEARCH/haskell2004.pdf&quot;&gt;&quot;I am not a Number -- I am a Free Variable&quot;&lt;/a&gt; to our running example to try to keep Conor's somewhat absurd sense of humor intact we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; me expr = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (letmeB &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; expr) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  letmeB this (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; you) | you == me = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; this
                      | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; you
  letmeB this (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; that)            = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; that
  letmeB this (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; fun arg)       = letmeB this fun `&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;` letmeB this arg
  letmeB this (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; body))  = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ letmeB (succ this) body

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; what (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; body) = what'sB &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; body &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  what'sB this (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; that) | this == that = what
                        | otherwise    = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; that
  what'sB this (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; you)                 = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; you
  what'sB this (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; fun arg)           = what'sB this fun `&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;` what'sB this arg
  what'sB this (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; body))      = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ what'sB (succ this) body

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, and is even slightly interesting.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could even make a monad that does capture avoiding substitution for &lt;code&gt;Exp&lt;/code&gt;, but it is an awkward one-off experience.&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) &lt;code&gt;Scope&lt;/code&gt;, &lt;code&gt;abstract&lt;/code&gt;, and &lt;code&gt;instantiate&lt;/code&gt; made it harder to screw up walking under binders.&lt;/p&gt;
&lt;p&gt;2.) Alpha equivalence is just &lt;code&gt;(==)&lt;/code&gt; due to the power of De Bruijn indices.&lt;/p&gt;
&lt;p&gt;3.) We &lt;em&gt;can&lt;/em&gt; make a &lt;code&gt;Monad&lt;/code&gt; for &lt;code&gt;Exp&lt;/code&gt; that does &lt;em&gt;capture avoiding&lt;/em&gt; substitution.&lt;/p&gt;
&lt;p&gt;4.) We can use &lt;code&gt;Traversable&lt;/code&gt; and &lt;code&gt;Foldable&lt;/code&gt; to find free variables and close terms.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Using&lt;/span&gt; these we can define combinators like
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable


&lt;span class=&quot;hljs-title&quot;&gt;closed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (f b)
&lt;span class=&quot;hljs-title&quot;&gt;closed&lt;/span&gt; = traverse (const &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;isClosed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;isClosed&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;.all (const &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;The types check out.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;to&lt;/span&gt; check for closed terms, and we can use `&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;` directly &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; a closed term.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) We &lt;code&gt;succ&lt;/code&gt; a lot in &lt;code&gt;letmeB&lt;/code&gt; and &lt;code&gt;what'sB&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;2.) Illegal terms such as &lt;code&gt;Lam (Scope (B 2))&lt;/code&gt; still exist.&lt;/p&gt;
&lt;p&gt;3.) We have to define one-off versions of &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; for each expression type we come up with. This means this is a design pattern, not a library.&lt;/p&gt;
&lt;p&gt;4.) The &lt;code&gt;Monad&lt;/code&gt; for &lt;code&gt;Exp&lt;/code&gt; is similarly a one-off deal.&lt;/p&gt;
&lt;h3 id=&quot;bird-and-paterson-part-1&quot;&gt;Bird and Paterson, Part 1&lt;/h3&gt;
&lt;p&gt;We can turn to Bird and Paterson's encoding of De Bruijn indices in terms of polymorphic recursion from the first half of &lt;a href=&quot;http://www.cs.uwyo.edu/~jlc/courses/5000_fall_08/debruijn_as_nested_datatype.pdf&quot;&gt;De Bruijn notation as a nested datatype&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a))
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; l r &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (l &amp;gt;&amp;gt;= f) (r &amp;gt;&amp;gt;= f)
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; xs &amp;gt;&amp;gt;= f = undefined &lt;span class=&quot;hljs-comment&quot;&gt;-- go for it!&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print &lt;span class=&quot;hljs-string&quot;&gt;&quot;Did you finish (&amp;gt;&amp;gt;=)?&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) This eliminates the illegal terms from Con #2 above once and for all, and we can write a one-off &lt;code&gt;Monad&lt;/code&gt; for it.&lt;/p&gt;
&lt;p&gt;2.) We have the &lt;code&gt;Maybe&lt;/code&gt; to mark our extra variables, so we can't forget to deal with our bound term at any point in our recursion.&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) We still &lt;code&gt;succ&lt;/code&gt; a lot, except now we call &lt;code&gt;succ&lt;/code&gt; &lt;code&gt;Just&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;2.) We still need to write one-off &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; combinators.&lt;/p&gt;
&lt;p&gt;3.) The &lt;code&gt;Monad&lt;/code&gt; for &lt;code&gt;Exp&lt;/code&gt; is a one-off deal.&lt;/p&gt;
&lt;p&gt;4.) They lean somewhat unnecessarily on &lt;code&gt;RankNTypes&lt;/code&gt; to manipulate these expressions in terms of their folds, when the &lt;code&gt;Monad&lt;/code&gt; and other classes can all be defined within the confines of &lt;a href=&quot;http://www.haskell.org/onlinereport/&quot;&gt;Haskell 98&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;attempt-1&quot;&gt;Attempt #1&lt;/h3&gt;
&lt;p&gt;We can modify Bird and Paterson's approach in a few ways, to steal some of the desirable properties from McBride's &quot;I am not a Number; I'm a Free Variable&quot; by noticing that Scope forms a Monad transformer!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Trans
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runScope&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; m &amp;gt;&amp;gt;= f = undefined &lt;span class=&quot;hljs-comment&quot;&gt;-- go for it!&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lift = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . liftM &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print &lt;span class=&quot;hljs-string&quot;&gt;&quot;Scope scopes out, but did you finish (&amp;gt;&amp;gt;=)?&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The astute observer will recognize that this form of &lt;code&gt;Scope&lt;/code&gt; is just &lt;a href=&quot;https://hackage.haskell.org/packages/archive/transformers/0.3.0.0/doc/html/Control-Monad-Trans-Maybe.html&quot;&gt;&lt;code&gt;MaybeT&lt;/code&gt;&lt;/a&gt; from &lt;a href=&quot;https://hackage.haskell.org/package/transformers&quot;&gt;&lt;code&gt;transformers&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can finally even define &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; from Conor's approach once and for all, completely independently of our expression type. Sadly, they find themselves now devoid of humor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a) =&amp;gt; a -&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; x xs = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (fmap go xs) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go y = y &amp;lt;$ guard (x /= y)

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; x (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; xs) = xs &amp;gt;&amp;gt;= go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; = x
  go (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; y) = return y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is starting to feel like a library, rather than design pattern.&lt;/p&gt;
&lt;p&gt;Moreover, with that in hand, we can revisit the definition of &lt;code&gt;Exp&lt;/code&gt; and define our &lt;code&gt;Monad&lt;/code&gt; by borrowing from &lt;code&gt;Scope&lt;/code&gt;'s expression-type-agnostic definition.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Trans
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runScope&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ m &amp;gt;&amp;gt;= maybe (return &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;) (runScope . f)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lift = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . liftM &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a) =&amp;gt; a -&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; x xs = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (fmap go xs) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go y = y &amp;lt;$ guard (x /= y)

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; x (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; xs) = xs &amp;gt;&amp;gt;= go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;  = x
  go (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; y) = return y


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a &amp;gt;&amp;gt;= f    = f a
  &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; l r &amp;gt;&amp;gt;= f  = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (l &amp;gt;&amp;gt;= f) (r &amp;gt;&amp;gt;= f)
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; body &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (body &amp;gt;&amp;gt;= lift . f)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;Now we're getting somewhere!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) We were able to factor out &lt;code&gt;Scope&lt;/code&gt;, &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; into code we can write once and package up.&lt;/p&gt;
&lt;p&gt;2.) We've gained the benefits of McBride's conventions, as &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; are really nice to reason about.&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) This is still going to &lt;code&gt;succ&lt;/code&gt; just as much as our earlier De Bruijn solutions. Using &lt;code&gt;lift&lt;/code&gt; to embed into &lt;code&gt;Scope&lt;/code&gt; has to traverse all of the leaves to mangle them with a &lt;code&gt;Just&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;2.) &lt;code&gt;Eq&lt;/code&gt; &lt;code&gt;Ord&lt;/code&gt;, &lt;code&gt;Show&lt;/code&gt;, and &lt;code&gt;Read&lt;/code&gt; are now non-trivial to write due to polymorphic recursion.&lt;/p&gt;
&lt;h3 id=&quot;bird-and-paterson-part-2&quot;&gt;Bird and Paterson, Part 2&lt;/h3&gt;
&lt;p&gt;Bird and Paterson did write the other half of their paper for a reason, though. In the other half they showed we can encode a &lt;em&gt;generalized&lt;/em&gt; De Bruijn index notion using a different polymorphic recursion pattern.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The astute observer will now note that this is looking a bit less like &lt;code&gt;MaybeT&lt;/code&gt;. So what happened?&lt;/p&gt;
&lt;p&gt;Normally when you work with De Bruijn indices you &lt;code&gt;succ&lt;/code&gt; only the variables down at the leaves.&lt;/p&gt;
&lt;p&gt;What Bird and Paterson's generalized De Bruijn form allows you to do is &lt;code&gt;Just&lt;/code&gt; née &lt;code&gt;succ&lt;/code&gt; whole trees at a time!&lt;/p&gt;
&lt;p&gt;If we adopt my &lt;code&gt;MonadTrans&lt;/code&gt; variant of McBride's &lt;code&gt;Scope&lt;/code&gt; as before, and generalize Bird and Paterson's approach, sticking to Haskell 98. We get very close to the final solution actually encoded in &lt;code&gt;bound&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Trans
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Maybe
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runScope&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; . return
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; e &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ e &amp;gt;&amp;gt;= \v -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; v &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; return &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; ea -&amp;gt; ea &amp;gt;&amp;gt;= runScope . f
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lift = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a) =&amp;gt; a -&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; a e = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (liftM k e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k b = return b &amp;lt;$ guard (a /= b)

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; e) = e &amp;gt;&amp;gt;= fromMaybe k

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;Almost there!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key difference realized by Bird and Paterson's design is that now, lifting an expression that does not have our bound term in it into our new &lt;code&gt;Scope&lt;/code&gt;, no longer requires touching every leaf in the expression. In fact it is &lt;code&gt;O(1)&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Scope&lt;/code&gt; is still a &lt;code&gt;Monad&lt;/code&gt; transformer, but it is a new one!&lt;/p&gt;
&lt;p&gt;This is a salvageable representation, but I want to take one more step before we turn it into a library, before we talk about Pros and Cons.&lt;/p&gt;
&lt;h3 id=&quot;bound-generalized-generalized-de-bruijn&quot;&gt;Bound: Generalized Generalized De Bruijn&lt;/h3&gt;
&lt;p&gt;Often we need to deal with simultaneous substitution of several variables. e.g. all of the variables bound by a pattern, all of the variables bound by a lambda, many variables bound by recursive let&lt;/p&gt;
&lt;p&gt;&lt;code&gt;De Bruijn&lt;/code&gt; even as generalized above still only lets me &lt;code&gt;abstract&lt;/code&gt; or &lt;code&gt;instantiate&lt;/code&gt; a single variable at a time.&lt;/p&gt;
&lt;p&gt;What I want relates to &lt;code&gt;EitherT&lt;/code&gt; as the above monad relates to &lt;code&gt;MaybeT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, I'm going to alpha rename &lt;code&gt;Either&lt;/code&gt;, because really when we &lt;em&gt;do&lt;/em&gt; finally get to show you these syntax trees, they are going to be bad enough without meaningless &lt;code&gt;Left&lt;/code&gt; and &lt;code&gt;Right&lt;/code&gt; names cluttering up my tree. Let's use &lt;code&gt;B&lt;/code&gt; for bound (pronounced &lt;code&gt;zero&lt;/code&gt;) and &lt;code&gt;F&lt;/code&gt; for free (pronounced &lt;code&gt;succ&lt;/code&gt;) in homage to Conor's conventions above.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Trans
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Maybe
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable

&lt;span class=&quot;hljs-comment&quot;&gt;-- show Var&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; b a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b
  | &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b &amp;gt;&amp;gt;= _ = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b

&lt;span class=&quot;hljs-comment&quot;&gt;-- show Scope&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runScope&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; . return
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; e &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ e &amp;gt;&amp;gt;= \v -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; v &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b  -&amp;gt; return (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b)
    &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; ea -&amp;gt; ea &amp;gt;&amp;gt;= runScope . f
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lift = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- show Abstraction and Instantiation&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; b) -&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b f a
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; f e = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (liftM k e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k y = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f y &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; z  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; z
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (return y)

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; (b -&amp;gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; k e = runScope e &amp;gt;&amp;gt;= \v -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; v &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b -&amp;gt; k b
  &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a -&amp;gt; a

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, therefore it must be correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here on out we can actually use the real &lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;p&gt;1.) Because we can now &lt;code&gt;succ&lt;/code&gt;/&lt;code&gt;F&lt;/code&gt; a whole tree, we don't have to pay the usual De Bruijn performance tax.
We get &lt;code&gt;O(1)&lt;/code&gt; lifting, and when we &lt;code&gt;instantiate&lt;/code&gt; we can skip past the whole &lt;code&gt;F&lt;/code&gt;'d tree.&lt;/p&gt;
&lt;p&gt;2.) We use &lt;code&gt;Foldable&lt;/code&gt; and &lt;code&gt;Traversable&lt;/code&gt; to extract information about free variables and do
variable -&amp;gt; variable substitution.&lt;/p&gt;
&lt;p&gt;3.) We can use the &lt;code&gt;MonadTrans&lt;/code&gt; instance for &lt;code&gt;Scope b&lt;/code&gt; to facilitate the construction of &lt;code&gt;Exp&lt;/code&gt;.
We do this so often that we turn the &lt;code&gt;&amp;gt;&amp;gt;= lift . f&lt;/code&gt; idiom into a combinator (&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/code&gt;)
that we'll talk about further when we talk about patterns.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;This&lt;/span&gt; is a complete example syntax tree example that supports the use &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;`/`&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;`/`&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt;`
&lt;span class=&quot;hljs-title&quot;&gt;to&lt;/span&gt; extract information about the free variables, and &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; capture-avoiding substitution!
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Bound

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
 = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
 | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
 | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; () &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
 | &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a] (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
 &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; l r &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (l &amp;gt;&amp;gt;= f) (r &amp;gt;&amp;gt;= f)
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; s &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (s &amp;gt;&amp;gt;&amp;gt;= f)
  &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; xs b &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; (map (&amp;gt;&amp;gt;&amp;gt;= f) xs) (b &amp;gt;&amp;gt;&amp;gt;= f)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;That's it!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;4.) We can now deal with simultaneous substitution. To make things interesting in the example above we've extended the example with a simultaneous binding for all of the variables in a recursive let!&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;1.) I still haven't shown you how to get &lt;code&gt;Eq&lt;/code&gt;, &lt;code&gt;Ord&lt;/code&gt;, &lt;code&gt;Read&lt;/code&gt;, &lt;code&gt;Show&lt;/code&gt; such that &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Ord&lt;/code&gt; respect alpha-equivalence.&lt;/p&gt;
&lt;h3 id=&quot;loose-ends&quot;&gt;Loose Ends&lt;/h3&gt;
&lt;p&gt;To work around the polymorphic recursion in &lt;code&gt;Scope&lt;/code&gt;, we turn to my fairly boring and generically named &lt;a href=&quot;https://hackage.haskell.org/package/prelude-extras&quot;&gt;&lt;code&gt;prelude-extras&lt;/code&gt;&lt;/a&gt; package. This package provides higher-rank versions of typeclasses from the &lt;code&gt;Prelude&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq1&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (==#) :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; t a -&amp;gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
  (/=#) :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; t a -&amp;gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;along with &lt;code&gt;Eq2&lt;/code&gt;, &lt;code&gt;Ord1&lt;/code&gt;, &lt;code&gt;Ord2&lt;/code&gt;, &lt;code&gt;Show1&lt;/code&gt;, &lt;code&gt;Show2&lt;/code&gt;, &lt;code&gt;Read1&lt;/code&gt; and &lt;code&gt;Read2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I told you it was boring.&lt;/p&gt;
&lt;p&gt;There has also been some discussion on the libraries mailing list of randomly renaming these things and putting (a subset?) of these in &lt;code&gt;transformers&lt;/code&gt; to permit Haskell 98 &lt;code&gt;Show&lt;/code&gt; instances things like &lt;code&gt;IdentityT&lt;/code&gt; and &lt;code&gt;WriterT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, what we can do is use the fact that these classes have default definitions and the instances for &lt;code&gt;Scope&lt;/code&gt; are defined in terms of &lt;code&gt;Eq1&lt;/code&gt;, &lt;code&gt;Ord1&lt;/code&gt;, &lt;code&gt;Show1&lt;/code&gt;, and &lt;code&gt;Read1&lt;/code&gt; for the base data type, to obtain the final solution!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Bound
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude.Extras

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; () &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  (&amp;lt;*&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a   &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (x &amp;gt;&amp;gt;= f) (y &amp;gt;&amp;gt;= f)
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; e   &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (e &amp;gt;&amp;gt;&amp;gt;= f)

&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; whnf f &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b -&amp;gt; whnf (instantiate1 a b)
  f'    -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f' a
&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; e = e

&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; v b = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (abstract1 v b)

&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; e@&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;{}   = e
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; $ toScope $ nf $ fromScope b
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; whnf f &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b -&amp;gt; nf (instantiate1 a b)
  f' -&amp;gt; nf f' `&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;` nf a

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It compiles&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can finally show syntax tree terms again.&lt;/p&gt;
&lt;p&gt;The instances of &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Ord&lt;/code&gt; for &lt;code&gt;Scope&lt;/code&gt; in particular are careful to compare only up to alpha-equivalence by quotienting out the placement of any internal &lt;code&gt;F&lt;/code&gt; levels in the tree as if they'd all been pushed out to the leaves.&lt;/p&gt;
&lt;p&gt;We can use &lt;code&gt;abstract1&lt;/code&gt; and &lt;code&gt;instantiate1&lt;/code&gt;, which are analogous to the &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;instantiate&lt;/code&gt; we were using before we generalized our generalized De Bruijn index representation to define things like smart constructors&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; v b = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (abstract1 v b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and evaluation strategies such as computing weak head normal form:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; whnf f &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b -&amp;gt; whnf (instantiate1 a b)
  f'    -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f' a
&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; e = e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing the &lt;code&gt;f (Maybe a)&lt;/code&gt; representation was good for was for walking under binders. &lt;code&gt;bound&lt;/code&gt; offers the round trip through this representation as &lt;code&gt;fromScope&lt;/code&gt; and &lt;code&gt;toScope&lt;/code&gt;. Now, if we need to walk under a lambda, we can!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; e@&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt;{}   = e
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; $ toScope $ nf $ fromScope b
&lt;span class=&quot;hljs-title&quot;&gt;nf&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; whnf f &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b -&amp;gt; nf (instantiate1 a b)
  f' -&amp;gt; nf f' `&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;` nf a
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;bound-class&quot;&gt;Bound.Class&lt;/h3&gt;
&lt;p&gt;Finally, it is worth commenting on the generality of &lt;code&gt;(&amp;gt;&amp;gt;&amp;gt;=)&lt;/code&gt; as it points to the class for which this package is named.&lt;/p&gt;
&lt;p&gt;In addition to &lt;code&gt;Scope&lt;/code&gt; and &lt;code&gt;Var&lt;/code&gt;, the &lt;code&gt;bound&lt;/code&gt; package provides the &lt;code&gt;Bound&lt;/code&gt; class:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;gt;&amp;gt;&amp;gt;=) :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; t f a -&amp;gt; (a -&amp;gt; f b) -&amp;gt; t f b
  &lt;span class=&quot;hljs-keyword&quot;&gt;default&lt;/span&gt; (&amp;gt;&amp;gt;&amp;gt;=) :: (&lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; t f a -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) -&amp;gt; t f b
  m &amp;gt;&amp;gt;&amp;gt;= f = m &amp;gt;&amp;gt;= lift . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An instance of &lt;code&gt;Bound&lt;/code&gt; is required to form a left module over all monads. That is to say it should satisfy the following two laws that were identified by Andrea Vezzosi:&lt;/p&gt;
&lt;p&gt;1.) The first such law is analogous to the first monad law:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;gt;&amp;gt;&amp;gt;= return ≡ m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.) The second such law is an associativity law:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;gt;&amp;gt;&amp;gt;= (λ x → k x &amp;gt;&amp;gt;= h) ≡ (m &amp;gt;&amp;gt;&amp;gt;= k) &amp;gt;&amp;gt;&amp;gt;= h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Trivially, any valid &lt;code&gt;MonadTrans&lt;/code&gt; instance satisfies these laws, hence the default definition.&lt;/p&gt;
&lt;p&gt;This extra flexibility is used in the &lt;a href=&quot;https://github.com/ekmett/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; &lt;a href=&quot;https://github.com/ekmett/bound/tree/master/examples&quot;&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt; folder to deal with complex pattern matching or other binding/telescoping structures.&lt;/p&gt;
&lt;h3 id=&quot;what-s-next&quot;&gt;What's Next?&lt;/h3&gt;
&lt;p&gt;You've just taken a crash course on name capture and been shown how &lt;code&gt;bound&lt;/code&gt; deals with common isses and makes it easy to work with De Bruijn indices without ever thinking about De Bruijn indices.&lt;/p&gt;
&lt;p&gt;Hopefully, you want to learn more. Perhaps after a slight break to let this settle. If so, I can offer you three further avenues for exploration off the top of my head.&lt;/p&gt;
&lt;p&gt;First, I'd like to note that there are a few middlingly-complex examples in the &lt;a href=&quot;https://github.com/ekmett/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; &lt;a href=&quot;https://github.com/ekmett/bound/tree/master/examples&quot;&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt; folder to explore and use as a template. Notably:&lt;/p&gt;
&lt;p&gt;1.) &lt;a href=&quot;https://github.com/ekmett/bound/blob/master/examples/Simple.hs&quot;&gt;&lt;code&gt;Simple.hs&lt;/code&gt;&lt;/a&gt; continues in the vein
we've taken here but fleshes out recursive let and sticks to Haskell 98 religiously.
2.)
&lt;a href=&quot;https://github.com/ekmett/bound/blob/master/examples/Deriving.hs&quot;&gt;&lt;code&gt;Deriving.hs&lt;/code&gt;&lt;/a&gt; takes over from
where we're leaving off with here and uses&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to reduce boilerplate, and importantly adds pattern matching. This showcases the need for the &lt;code&gt;Bound&lt;/code&gt;
class for dealing with patterns, case alternatives, and similar module structures.&lt;/p&gt;
&lt;p&gt;3.) &lt;a href=&quot;https://github.com/ekmett/bound/blob/master/examples/Overkill.hs&quot;&gt;&lt;code&gt;Overkill.hs&lt;/code&gt;&lt;/a&gt; offers a trip down the rabbit hole of type safety. It shows how strong the type guarantees &lt;em&gt;can&lt;/em&gt; get, by using custom kinds to index into its patterns and improves the safety of pattern matching and let binding over and above the &lt;code&gt;Deriving.hs&lt;/code&gt; approach, but at the expense of a great deal more code!&lt;/p&gt;
&lt;p&gt;Second, it is also possible to derive a higher order version of &lt;code&gt;bound&lt;/code&gt; that can deal with strongly typed EDSLs as well. I've included a worked example version of it here under a spoiler tag simply for completeness, including an example of what could be turned into a network serializable EDSL replete with local variable bindings and lambdas, but it isn't for the faint of heart. It is also probably buggy and is completely untested. If you fix any issues with it, please feel free to email me!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs, Rank2Types, KindSignatures, ScopedTypeVariables, TypeOperators, DataKinds, PolyKinds, MultiParamTypeClasses, FlexibleInstances, TypeFamilies, DoRec, ExtendedDefaultRules #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Category
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Fix
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad (&lt;span class=&quot;hljs-title&quot;&gt;ap&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor.Identity
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Typeable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Unique
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; System.IO.Unsafe
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Unsafe.Coerce
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; ((.),id)

&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;gt;&amp;gt;&amp;gt;-, &amp;gt;&amp;gt;-

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f g = forall x. f x -&amp;gt; g x&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hmap :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f g -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; (t f) (t g)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  htraverse :: &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; m =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; m (g x)) -&amp;gt; t f a -&amp;gt; m (t g a)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hreturn :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f (t f)
  (&amp;gt;&amp;gt;-)   :: t f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f (t g) -&amp;gt; t g a

&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; -&amp;lt;&amp;lt;
(-&amp;lt;&amp;lt;) :: &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f (t g) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; (t f) (t g)
&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; -&amp;lt;&amp;lt; m = m &amp;gt;&amp;gt;- f
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HBound&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;gt;&amp;gt;&amp;gt;-) :: &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; s t f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f (t g) -&amp;gt; s t g a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonadTrans&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hlift :: &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; (t f) (s t f)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; b f a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; :: b a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; b f a
  &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; b f a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hmap _ (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (f a)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  htraverse _ (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b) = pure (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b)
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &amp;lt;$&amp;gt; f a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hreturn   = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b &amp;gt;&amp;gt;- _ = &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b
  &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a &amp;gt;&amp;gt;- f = f a

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b t f a = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unscope&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (hmap (hmap (hmap f)) b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &amp;lt;$&amp;gt; htraverse (htraverse (htraverse f)) b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hreturn = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . hreturn . &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; . hreturn
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; e &amp;gt;&amp;gt;- f  = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; $ e &amp;gt;&amp;gt;- \v -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; v &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b -&amp;gt; hreturn (&lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b)
    &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; ea -&amp;gt; ea &amp;gt;&amp;gt;- unscope . f
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonadTrans&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hlift = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . hreturn . &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HBound&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; m &amp;gt;&amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (hmap (hmap (&amp;gt;&amp;gt;- f)) m)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Equal&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Equal&lt;/span&gt; a a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Equal&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id = &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (b x)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; (t f) (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b t f)
&lt;span class=&quot;hljs-title&quot;&gt;abstract&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; . hmap (\y -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f y &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b
  &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (hreturn y))

&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; b (t f) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; b t f) (t f)
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; e) = e &amp;gt;&amp;gt;- \v -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; v &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;B&lt;/span&gt; b -&amp;gt; k b
  &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a -&amp;gt; a

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; :: [*] -&amp;gt; * -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; (a ': &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) a
  &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; (a ': &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) b

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; :: (* -&amp;gt; *) -&amp;gt; [*] -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f '[]
  (:::) :: f b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f bs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f (b ': bs)

&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; :++, :::

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;family&lt;/span&gt; (:++) (&lt;span class=&quot;hljs-title&quot;&gt;as&lt;/span&gt; :: [*]) (&lt;span class=&quot;hljs-title&quot;&gt;bs&lt;/span&gt; :: [*]) :: [*]&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance '[] :++ bs = bs&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ': &lt;span class=&quot;hljs-title&quot;&gt;as&lt;/span&gt;) :++ bs = a ': (&lt;span class=&quot;hljs-title&quot;&gt;as&lt;/span&gt; :++ &lt;span class=&quot;hljs-title&quot;&gt;bs&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;happend&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f bs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f (&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; :++ bs)
&lt;span class=&quot;hljs-title&quot;&gt;happend&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt; bs = bs
&lt;span class=&quot;hljs-title&quot;&gt;happend&lt;/span&gt; (a ::: &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) bs = a ::: happend &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs

&lt;span class=&quot;hljs-title&quot;&gt;hsingleton&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f '[a]
&lt;span class=&quot;hljs-title&quot;&gt;hsingleton&lt;/span&gt; x = x ::: &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hmap _ &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt;
  hmap f (x ::: xs) = f x ::: hmap f xs
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  htraverse _ &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt; = pure &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt;
  htraverse f (x ::: xs) = (:::) &amp;lt;$&amp;gt; f x &amp;lt;*&amp;gt; htraverse f xs
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;EqF&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (==?) :: f a -&amp;gt; f b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Equal&lt;/span&gt; a b)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;  :: &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;EqF&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; a ==? &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; b = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt;
  ...

&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; i) = i
&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; d) = d
&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; s) = s
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Literal&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  literal :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Literal&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  literal = &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Literal&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  literal = &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; :: (* -&amp;gt; *) -&amp;gt; * -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a
  &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Equal&lt;/span&gt; b) &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f (b -&amp;gt; a)
  &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; bs) &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f) bs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Scope&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; bs) &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a
  &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt;  :: &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f (a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f b

&lt;span class=&quot;hljs-title&quot;&gt;lam_&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;EqF&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;lam_&lt;/span&gt; v f = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (abstract (v ==?) f)

&lt;span class=&quot;hljs-title&quot;&gt;lit&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Literal&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;lit&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; . literal
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HFunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a)    = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; (f a)
  hmap _ (&lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t)    = &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b)    = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (hmap f b)
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; bs b) = &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; (hmap (hmap f) bs) (hmap f b)
  hmap f (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; x y)   = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; (hmap f x) (hmap f y)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a)    = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; &amp;lt;$&amp;gt; f a
  htraverse _ (&lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t)    = pure $ &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b)    = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &amp;lt;$&amp;gt; htraverse f b
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; bs b) = &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; &amp;lt;$&amp;gt; htraverse (htraverse f) bs &amp;lt;*&amp;gt; htraverse f b
  htraverse f (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; x y)   = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; &amp;lt;$&amp;gt; htraverse f x &amp;lt;*&amp;gt; htraverse f y

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MyF&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Mean&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;MyF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HMonad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  hreturn        = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a    &amp;gt;&amp;gt;- f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t    &amp;gt;&amp;gt;- _ = &lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; t
  &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b    &amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (b &amp;gt;&amp;gt;&amp;gt;- f)
  &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; bs b &amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; (hmap (&amp;gt;&amp;gt;&amp;gt;- f) bs) (b &amp;gt;&amp;gt;&amp;gt;- f)
  &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; x y   &amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; (x &amp;gt;&amp;gt;- f) (y &amp;gt;&amp;gt;- f)

(!) :: &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; f v -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; v a -&amp;gt; f a
(b ::: _)  ! &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;   = b
(_ ::: bs) ! &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n = bs ! n

&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; w) = extract w
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lit&lt;/span&gt; i) = value i
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b) = \a -&amp;gt; eval (instantiate (\&lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a)) b)
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; bs b) = eval (instantiate (vs !) b) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; vs = hmap (instantiate (vs !)) bs
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; x y) = eval x (eval y)

&lt;span class=&quot;hljs-title&quot;&gt;closed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HTraversable&lt;/span&gt; t =&amp;gt; t f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (t g a)
&lt;span class=&quot;hljs-title&quot;&gt;closed&lt;/span&gt; = htraverse (const &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :: *) = &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Unique&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;EqF&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a ==? &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; b
    | a == b    = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (unsafeCoerce &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt;)
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; f = unsafePerformIO $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  x &amp;lt;- fmap &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; newUnique
  return $ &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; $ abstract (x ==?) $ f $ &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; x

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Binding&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a := &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;rhs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Binding&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;rhs&lt;/span&gt; (_ := a) = a

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; = forall bs. &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;bs&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;elemIndex&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Vec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Binding&lt;/span&gt; bs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ix&lt;/span&gt; bs a)
&lt;span class=&quot;hljs-title&quot;&gt;elemIndex&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt;              _ = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;elemIndex&lt;/span&gt; ((x := r) ::: xs) y = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; x ==? y &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Refl&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &amp;lt;$&amp;gt; elemIndex xs y
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HNil&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; xs `mappend` &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; ys = &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; (happend xs ys)

&lt;span class=&quot;hljs-comment&quot;&gt;-- Allow the use of DoRec to define let statements&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runDef&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    (a,w) &amp;lt;- m
    return (f a, w)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = return
  (&amp;lt;*&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ return (a, mempty)
  &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    (a, xs) &amp;lt;- m
    (b, ys) &amp;lt;- runDef (f a)
    return (b, xs &amp;lt;&amp;gt; ys)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFix&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mfix m = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ mfix $ \ ~(a, _) -&amp;gt; runDef (m a)

&lt;span class=&quot;hljs-title&quot;&gt;def&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;def&lt;/span&gt; v@&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt;{} = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ return (v, mempty) &lt;span class=&quot;hljs-comment&quot;&gt;-- this thing already has a name&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;def&lt;/span&gt; r = &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  v &amp;lt;- fmap &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; newUnique
  return (&lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; v, &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; (hsingleton (v := r)))

&lt;span class=&quot;hljs-title&quot;&gt;let_&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Remote&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;let_&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Def&lt;/span&gt; m) = unsafePerformIO $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    (r, &lt;span class=&quot;hljs-type&quot;&gt;Bindings&lt;/span&gt; bs) &amp;lt;- m
    return $ &lt;span class=&quot;hljs-type&quot;&gt;Let&lt;/span&gt; (hmap (abstract (elemIndex bs) . rhs) bs)
                 (abstract (elemIndex bs) r)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Third, for a much larger &quot;industrial scale&quot; example you can explore our work-in-progress &lt;a href=&quot;https://github.com/ermine-language/ermine&quot;&gt;compiler for Ermine&lt;/a&gt; that uses &lt;a href=&quot;https://github.com/ekmett/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; (and &lt;a href=&quot;https://github.com/ekmett/lens&quot;&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt;) extensively for manipulating its &lt;a href=&quot;http://ermine-language.github.io/ermine/Ermine-Syntax-Term.html&quot;&gt;&lt;code&gt;Term&lt;/code&gt;&lt;/a&gt; language, &lt;a href=&quot;http://ermine-language.github.io/ermine/Ermine-Syntax-Type.html&quot;&gt;&lt;code&gt;Type&lt;/code&gt;&lt;/a&gt; system, &lt;a href=&quot;http://ermine-language.github.io/ermine/Ermine-Syntax-Kind.html&quot;&gt;&lt;code&gt;Kind&lt;/code&gt;&lt;/a&gt; system and the &lt;a href=&quot;http://ermine-language.github.io/ermine/Ermine-Syntax-Core.html&quot;&gt;&lt;code&gt;Core&lt;/code&gt;&lt;/a&gt; language it spits out as a witness during type checking.&lt;/p&gt;
&lt;p&gt;Happy Hacking!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 19 2013&lt;/p&gt;
&lt;p&gt;P.S. Apparently the proper Dutch convention with names is to use &lt;a href=&quot;http://en.wikipedia.org/wiki/Nicolaas_Govert_de_Bruijn&quot;&gt;Nicolaas Govert de Bruijn&lt;/a&gt; when writing out a full name, but to capitalize De Bruijn when using the surname in isolation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/bound/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Propagators</title><link>https://comonad.com/reader/talks/youtube-DyPzPeOPgUE/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-DyPzPeOPgUE/</guid><pubDate>Wed, 18 Nov 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 November 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;DyPzPeOPgUE&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DyPzPeOPgUE&quot;&gt;Watch on YouTube&lt;/a&gt; · 113 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Recorded on Nov 18, 2015&lt;br&gt;
&lt;a href=&quot;http://www.meetup.com/Boston-Haskell/events/224740729/&quot;&gt;http://www.meetup.com/Boston-Haskell/events/224740729/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-DyPzPeOPgUE/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Servant</title><link>https://comonad.com/reader/talks/youtube-rsv96JK4Vx4/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-rsv96JK4Vx4/</guid><pubDate>Wed, 04 Nov 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Julian Arni · 4 November 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;rsv96JK4Vx4&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rsv96JK4Vx4&quot;&gt;Watch on YouTube&lt;/a&gt; · 151 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Julian Arni delivers a marathon talk on Servant for the Boston Haskell Users Group. Recorded November 4th, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://haskell-servant.github.io/&quot;&gt;http://haskell-servant.github.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.meetup.com/Boston-Haskell/events/226374552/&quot;&gt;http://www.meetup.com/Boston-Haskell/events/226374552/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-rsv96JK4Vx4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>csound-expression</title><link>https://comonad.com/reader/talks/youtube-O0oBXcwGZQY/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-O0oBXcwGZQY/</guid><pubDate>Wed, 21 Oct 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Paul Chiusano · 21 October 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;O0oBXcwGZQY&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=O0oBXcwGZQY&quot;&gt;Watch on YouTube&lt;/a&gt; · 88 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Paul Chiusano gives Boston Haskell a demo of the csound system (&lt;a href=&quot;https://csound.github.io/&quot;&gt;https://csound.github.io/&lt;/a&gt;) and its Haskell expression library (&lt;a href=&quot;https://hackage.haskell.org/package/csound-expression&quot;&gt;https://hackage.haskell.org/package/csound-expression&lt;/a&gt;). Recorded on Oct. 21, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-O0oBXcwGZQY/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Fibonacci — Part 2: Open-Ended Fibonacci Search</title><link>https://comonad.com/reader/2015/fibonacci-search/</link><guid isPermaLink="false">https://comonad.com/reader/2015/fibonacci-search/</guid><pubDate>Tue, 13 Oct 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 13 October 2015&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/fibonacci-leonardo/&quot;&gt;Last time&lt;/a&gt;, I built a form of random access list with &lt;em&gt;O(1)&lt;/em&gt; cons using the Leonardo numbers and emphasized that the slight skew in the tree could be a good thing.&lt;/p&gt;
&lt;p&gt;Now I want to do some searching, but after all, I'm a functional programmer and everybody knows all we do all day is play with ways to write &lt;code&gt;fib&lt;/code&gt;, so we'll start by building an industrial strength version of the &lt;code&gt;fib&lt;/code&gt; function to get a feel for how the Fibonacci numbers fit together, and then maybe we can turn it into something with which we can perform efficient searches.&lt;/p&gt;
&lt;h2 id=&quot;integral-domains&quot;&gt;Integral Domains&lt;/h2&gt;
&lt;p&gt;To avoid lying, let's stop and define the notion of an integral domain, which is any non-zero commutative ring in which there are no non-zero zero divisors; if &lt;code&gt;a*b = 0&lt;/code&gt; then either &lt;code&gt;a = 0&lt;/code&gt;, or &lt;code&gt;b = 0&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rational&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The latter only pass the no non-zero zero divisors test if you ignore underflow, and I'd probably be beaten up for pretending they are a ring. For the sake of the code at hand we're okay with them, but delete these instances if they make you uncomfortable! I'm not using them.&lt;/p&gt;
&lt;h2 id=&quot;homogeneous-linear-recurrences&quot;&gt;Homogeneous Linear Recurrences&lt;/h2&gt;
&lt;p&gt;I mentioned last time that you could compute Leonardo and Fibonacci numbers in logarithmic time using the fact that they were linear recurrence relationships. Bill Gosper and Richard Schroeppel called this technique the &lt;a href=&quot;http://www.inwap.com/pdp10/hbaker/hakmem/recurrence.html&quot;&gt;&quot;Fast Fibonacci Transform&quot;&lt;/a&gt; in HAKMEM, a collection of number theoretic computing tricks from the MIT AI Lab from back in the early 70s.&lt;/p&gt;
&lt;p&gt;Now, I confess, I lied a little bit by saying this. Technically you need the fact that you have a &lt;em&gt;homogeneous&lt;/em&gt; linear recurrence relationship.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;X&lt;/span&gt;*&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt;-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) + &lt;span class=&quot;hljs-type&quot;&gt;Y&lt;/span&gt;*(&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt;-&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note how no additional constant is being added in. While the Leonardo recurrence doesn't meet this criterion, it is fortunate that the related recurrence&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;leo&lt;/span&gt; n = leonardo n + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; = leonardo (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) + leonardo (n-&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) + &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; = leo (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) + leo (n-&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;does. In fact, &lt;code&gt;leo&lt;/code&gt; satisfies the same recurrence as in the Fibonacci numbers, and after plugging in some constants we find that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;leo&lt;/span&gt; n = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * fib (n+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which gives rise to the formula for Leonardo numbers in terms of Fibonacci numbers that I gave last time:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;leonardo&lt;/span&gt; n = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * fib (n+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dijkstra talks more about this specific relationship between the Fibonacci and Leonardo sequences in &lt;a href=&quot;http://www.cs.utexas.edu/users/EWD/transcriptions/EWD07xx/EWD797.html&quot;&gt;EWD797&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;r&quot;&gt;R[φ]&lt;/h2&gt;
&lt;p&gt;The HAKMEM writeup gives a form of multiplication for an arbitrary homogeneous linear recurrence relationship, but we only need the Fibonacci recurrence today. We can take the number type described in HAKMEM and turn it directly into a Haskell data type.&lt;/p&gt;
&lt;p&gt;I'm interested in numbers of the form &lt;code&gt;aφ+b&lt;/code&gt;, where &lt;code&gt;φ ~ 1.6180339887...&lt;/code&gt; is the golden ratio.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ = (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;+√&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;)/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another fancier way to think of it formally is that we're working in &lt;code&gt;Z[x] mod x^2 - x - 1&lt;/code&gt; and the polynomial &lt;code&gt;x^2 - x - 1&lt;/code&gt; has two roots: &lt;code&gt;(1+√5)/2&lt;/code&gt; and &lt;code&gt;(1-√5)/2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Addition and subtraction are done pointwise as in complex arithmetic.&lt;/p&gt;
&lt;p&gt;We can work through multiplication fairly directly by exploiting the interesting fact that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; = φ+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(aφ+b)(cφ+d) = ac(φ+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) + (ad+bc)φ + bd = (ac+ad+bc)φ + (ac+bd) = (a(c+d)+bc)φ + (ac+bd)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turning this into a data type &lt;code&gt;Fib r&lt;/code&gt; where the data constructor &lt;code&gt;Fib a b&lt;/code&gt; represents &lt;code&gt;aφ + b&lt;/code&gt; in the ring extension &lt;code&gt;r[φ]&lt;/code&gt; we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt;&lt;/span&gt;
  (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b + &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a + c) (b + d)
  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b * &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a*(c + d) + b*c) (a*c + b*d)
  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b - &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a - c) (b - d)
  negate (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (negate a) (negate b)
  abs x = x
  signum _ = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- meh&lt;/span&gt;
  fromInteger n = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; (fromInteger n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why an &lt;code&gt;IntegralDomain&lt;/code&gt;? At the least we rely on the ability to commute multiplication to get this definition. In practice, we'd probably just presume &lt;code&gt;Num&lt;/code&gt; has whatever properties we need, and skip this requirement. We should otherwise be able to weaken it to a &lt;code&gt;CommutativeRing&lt;/code&gt; without lying.&lt;/p&gt;
&lt;p&gt;I'm not too happy with the &lt;code&gt;abs&lt;/code&gt;/&lt;code&gt;signum&lt;/code&gt; in there, but then nobody is really happy with them in Haskell, and these
pass the only law we require in Haskell for them, that &lt;code&gt;abs a * signum a = a&lt;/code&gt;, hence &lt;code&gt;abs = id&lt;/code&gt;, &lt;code&gt;signum = 1&lt;/code&gt; should always be admissable. Doing better requires an &lt;code&gt;Ord a&lt;/code&gt;, and rules out potentially many good uses for this ring extension.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;a&lt;/code&gt; was an integral domain then so is &lt;code&gt;Fib a&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can represent&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;without any loss of precision in this representation without doing symbolic computation.&lt;/p&gt;
&lt;p&gt;If we know more about &lt;code&gt;a&lt;/code&gt;, we can extend this ring to a field. In our simplistic numerical tower:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field&lt;/span&gt; a
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field&lt;/span&gt; a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  recip (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (-a/d) ((a+b)/d) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    d = b*b + a*b - a*a
  fromRational r = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; (fromRational r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is just a claim that this is a field extension.&lt;/p&gt;
&lt;p&gt;But, it turns out we don't need any of that &lt;code&gt;Fractional&lt;/code&gt; nonsense for &lt;code&gt;fib&lt;/code&gt;. After all Fibonacci numbers, even the negative ones, are whole numbers! In this ring, φ has an interesting property: It is a &quot;unit&quot; of this ring, which is to say it has an inverse, even if we don't have inverses for general elements. We can generate it algebraically from the same simple claim we used to figure out multiplication&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; = φ+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;by multiplying on the left by &lt;code&gt;φ^(-1)&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ = φ^(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) * φ^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; = φ^(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) * (φ+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + φ^(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;φ^(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) = φ - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can check our work by using the formula for &lt;code&gt;recip&lt;/code&gt;. If we fix the argument to φ, we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recip&lt;/span&gt; φ = recip (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; / -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;/ -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; * -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; * -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only division we needed was by &lt;code&gt;-1&lt;/code&gt;, which is a unit in the integers as &lt;code&gt;-1 * -1 = 1&lt;/code&gt;. Being a unit means we can replace division by -1 with multiplication by its inverse (also &lt;code&gt;-1&lt;/code&gt;), which we know exists in our ring.&lt;/p&gt;
&lt;p&gt;As a further aside, we can also represent &lt;code&gt;√5&lt;/code&gt; without requiring us to work over anything more than an integral domain.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;√&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;*φ - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clearly, &lt;code&gt;phi&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;recip phi&lt;/code&gt;, and &lt;code&gt;√5&lt;/code&gt; all have a very complicated relationship status.&lt;/p&gt;
&lt;h2 id=&quot;putting-r-in-order&quot;&gt;Putting R[φ] in Order&lt;/h2&gt;
&lt;p&gt;You can implement &lt;code&gt;Ord&lt;/code&gt; in a manner compatible with the answers given by more traditional numeric types, but it is a bit tricky.&lt;/p&gt;
&lt;p&gt;First we check for a quick exit if both results are consistent. It is only when the sign &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; differ in &lt;code&gt;aφ + b&lt;/code&gt; that we have a problem, which is bigger? &lt;code&gt;aφ&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;We can write a recursive solution that computes repeated remainders, &lt;code&gt;gcd&lt;/code&gt; style, but we actually hit literally the worst case possible for the usual &lt;code&gt;gcd&lt;/code&gt; algorithm for &lt;code&gt;Fib 1 (-1) ^ n&lt;/code&gt;. This is &lt;a href=&quot;http://www.cut-the-knot.org/blue/LamesTheorem.shtml&quot;&gt;Lamé's Theorem&lt;/a&gt; showing up in the wild, and these numbers show up below!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare a c &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; | b &amp;lt;= d    -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt;
       | otherwise -&amp;gt; go compare (a-c) (b-d)
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; compare b d
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; | b &amp;gt;= d    -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt;
       | otherwise -&amp;gt; go (flip compare) (a-c) (b-d)
   &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
     go k e f = k (sq (e+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;*f)) (&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;*sq e)
     sq x = x*x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So instead, in the above instance I convert to &lt;code&gt;aφ + b&lt;/code&gt; to &lt;code&gt;e√5 + f&lt;/code&gt; and compare the squares instead. This works nicely even when &lt;code&gt;a&lt;/code&gt; is &lt;code&gt;Double&lt;/code&gt; and is capable of representing &lt;code&gt;√5&lt;/code&gt; (more or less) on its own.&lt;/p&gt;
&lt;p&gt;With this &lt;code&gt;Ord&lt;/code&gt; instance in hand we could redefine the notion of &lt;code&gt;abs&lt;/code&gt; and &lt;code&gt;signum&lt;/code&gt; in &lt;code&gt;Num&lt;/code&gt; above to be compatible with the real number line, but to do so, you'd have to give up instances that aren't in &lt;code&gt;Ord&lt;/code&gt;, for example &lt;code&gt;Fib (Complex Double)&lt;/code&gt;. This just goes to show that &lt;code&gt;abs&lt;/code&gt;/&lt;code&gt;signum&lt;/code&gt; being placed directly in &lt;code&gt;Num&lt;/code&gt; was a bad idea.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exercise:&lt;/strong&gt; Why?&lt;/p&gt;
&lt;p&gt;Note that even this comes at a price. We have to similarly complicate the &lt;code&gt;Eq&lt;/code&gt; instance, replacing the automatically derived one we start with with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  x == y = compare x y == &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Exercise:&lt;/strong&gt; Why?&lt;/p&gt;
&lt;p&gt;With that in mind you'd probably want to make a separate data type if you actually cared about this ordering anyways. =(&lt;/p&gt;
&lt;p&gt;Nothing stops us from wiring this type up with instances for use with &lt;code&gt;linear&lt;/code&gt; as a vector space:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a a
  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a c) (b d)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a a
  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a' b' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a' _ = f a
    &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; _ b' = f b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadZip&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (f a c) (f b d)
  munzip (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a,b) (c,d)) = (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a c, &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; b d)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zero = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  (^+^) = (+)
  (^-^) = (-)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it may wind up in there at some point if I get bored.&lt;/p&gt;
&lt;h2 id=&quot;the-fast-fibonacci-transform&quot;&gt;The Fast Fibonacci Transform&lt;/h2&gt;
&lt;p&gt;If we're extending a ring/field with φ, why did I call it &lt;code&gt;Fib&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Well, with one more observation, we can now write the efficient notion of &lt;code&gt;fib&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let's take our multiplication formula&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b * &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; c d = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a*(c + d) + b*c) (a*c + b*d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and consider the effect of multiplying by φ:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b * φ = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a b * &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a*(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;+&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)+b*&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (a*&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + b*&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (a+b) a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Multiplying by φ shifts &lt;code&gt;a&lt;/code&gt; to the right, and adds the previous &lt;code&gt;b&lt;/code&gt;. This is the same structure as the
&quot;cursor&quot; we used last time when the number to the right is the previous Fibonacci number!&lt;/p&gt;
&lt;p&gt;This gives us&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (fib n) (fib (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)) * φ = &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; (fib (n+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)) (fib n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(The above formula can be rearranged to see why the ratio between consecutive Fibonacci numbers tends to φ in the limit.)&lt;/p&gt;
&lt;p&gt;Of course, we can compute &lt;code&gt;(^)&lt;/code&gt; using peasant exponentiation, by repeated squaring rather than
working one factor at a time. This is what Lennart's version of &lt;code&gt;(^)&lt;/code&gt; which is used by GHC today
does for us already, so we don't need to write it.&lt;/p&gt;
&lt;p&gt;With that:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;getPhi&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;getPhi&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; a _) = a

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Compute the nth Fibonacci number in O(log n)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fib&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntegralDomain&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fib&lt;/span&gt; n
  | n &amp;gt;= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = getPhi (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; ^ n)
  | otherwise = getPhi (&lt;span class=&quot;hljs-type&quot;&gt;Fib&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) ^ negate n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has the benefit of nicely extending to negative Fibonacci, unlike the usual boring definitions people tend to write. Moreover, if we don't &lt;code&gt;getPhi&lt;/code&gt; at the end then we get both the desired Fibonacci number and the preceding Fibonacci number, which is precisely what we need in order to move around in the sequence with &lt;code&gt;Fib&lt;/code&gt; as our &quot;cursor&quot;!&lt;/p&gt;
&lt;p&gt;As mentioned earlier, this same technique can be used to jump quickly to any element of any homogeneous linear recurrence in &lt;code&gt;O(log n)&lt;/code&gt; time and we can navigate from there, so we're not limited to doing this with Fibonacci numbers. You can jump around in any recurrence you like.&lt;/p&gt;
&lt;h2 id=&quot;fibonacci-search&quot;&gt;Fibonacci Search&lt;/h2&gt;
&lt;p&gt;Remember why I got started here? Oh yeah, there was something about searching.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Fibonacci_search_technique&quot;&gt;Fibonacci search&lt;/a&gt; was invented back in the 50s by &lt;a href=&quot;http://en.wikipedia.org/wiki/Jack_Kiefer_(statistician)&quot;&gt;Jack Kiefer&lt;/a&gt;. It is traditionally defined in terms of a closed space we want to search.&lt;/p&gt;
&lt;p&gt;To search using the Fibonacci sequence we slightly modify the binary-tree like nature of binary search to use Fibonacci numbers instead.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;E.g.&lt;/em&gt; given 100 elements, you find the first Fibonacci number &amp;gt;= 100 and use that as your high end, and start below at 0.&lt;/p&gt;
&lt;p&gt;If we have a Fibonacci number of elements, then instead of dividing in half, we can divide it into biased halves with sizes based on the two previous Fibonacci numbers. You can pick if you want the smaller on the left or the right and test the &quot;midpoint&quot; like traditional binary search. This is a fun programming exercise.&lt;/p&gt;
&lt;h2 id=&quot;open-ended-fibonacci-search&quot;&gt;Open-Ended Fibonacci Search&lt;/h2&gt;
&lt;p&gt;But what about unbounded search?&lt;/p&gt;
&lt;p&gt;An &quot;upwardly closed predicate&quot; &lt;code&gt;p&lt;/code&gt; on the natural numbers is a predicate &lt;code&gt;p :: Natural -&amp;gt; Bool&lt;/code&gt; for which there exists &lt;code&gt;n&lt;/code&gt;, such that &lt;code&gt;p n&lt;/code&gt; holds, and for all k, &lt;code&gt;p k&lt;/code&gt; implies &lt;code&gt;p (succ k)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Given an upwardly closed predicate, open-ended binary searching proceeds by repeatedly squaring a power of 2, until it finds an upper bound which passes the predicate, then binary searching within the resulting interval.&lt;/p&gt;
&lt;p&gt;But with the machinery above it is easy to see that we can do this same thing now with repeated squaring of φ to get results of form &lt;code&gt;aφ + b&lt;/code&gt;, where &lt;code&gt;a = fib(2^i)&lt;/code&gt;, &lt;code&gt;b = fib(2^i - 1)&lt;/code&gt; until &lt;code&gt;p a&lt;/code&gt; holds, then we have the two consecutive Fibonacci numbers &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt;, where &lt;code&gt;b&lt;/code&gt; is the size of one of the two branches we want to cut &lt;code&gt;a&lt;/code&gt; into, and &lt;code&gt;a-b&lt;/code&gt; is the other, and we know the predicate holds at &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From there we're well equipped to start a traditional Fibonacci search.&lt;/p&gt;
&lt;h2 id=&quot;ripping-out-all-the-math&quot;&gt;Ripping Out All The Math&lt;/h2&gt;
&lt;p&gt;Once we inline all the arithmetic needed for repeated squaring into &lt;code&gt;bound&lt;/code&gt; and merge all the manipulations of the cursors which are effectively just multiplications by &lt;code&gt;φ^-1&lt;/code&gt;, and assuming I haven't made the standard undergraduate mistake of screwing up binary search, we get a completely self-contained implementation:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;search&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;search&lt;/span&gt; p
  | p &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  | otherwise = bound &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    bound !a !b
     | p b = go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; a b
     | bb &amp;lt;- b*b = bound (a*a+bb) (bb+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;*a*b)
    &lt;span class=&quot;hljs-comment&quot;&gt;-- the answer lies in the interval (l,l+k], i,j,k are consecutive Fibonacci numbers.&lt;/span&gt;
    go !l !j !k
      | k == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;    = l + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
      | p m       = go l (j-i) i
      | otherwise = go m i j
      &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
        m = l + i
        i = k - j
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that, things like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; search (&amp;gt;&lt;span class=&quot;hljs-number&quot;&gt;12389012380128301283012381203912380192830123801283120931203&lt;/span&gt;)
&lt;span class=&quot;hljs-number&quot;&gt;12389012380128301283012381203912380192830123801283120931204&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;are effectively instantaneous.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NB:&lt;/em&gt; This version wastes a tiny bit of effort. When we finish with &lt;code&gt;bound&lt;/code&gt; we'd know the predicate &lt;code&gt;p&lt;/code&gt; failed for &lt;code&gt;fib (2^(i-1))&lt;/code&gt;, not just &lt;code&gt;fib 0&lt;/code&gt;, but the interval size between &lt;code&gt;fib (2^(i-1))&lt;/code&gt; and &lt;code&gt;fib (2^i)&lt;/code&gt; has no nice expression in terms of Fibonacci numbers. We could break &lt;code&gt;go&lt;/code&gt; up into two functions with one for use as long as your candidate range includes this better lower bound, or we could just clutter things up with an additional test to avoid these redundant probes.&lt;/p&gt;
&lt;p&gt;We could also just bias the result upward by &lt;code&gt;fib(2^(i-1))&lt;/code&gt; and search a window starting from there relying on our bias to avoid heavily searching the known hits at the top. The best choice really depends on the cost of the predicate and how that cost grows as the argument to it increases.&lt;/p&gt;
&lt;h2 id=&quot;further-thoughts&quot;&gt;Further Thoughts&lt;/h2&gt;
&lt;p&gt;By repeatedly squaring the index of the Fibonacci number in question we're shooting through the list of Fibonacci numbers quickly, so we'll find a bound pretty fast. Approximately every 5th index adds a digit to the result but we're doubling the index every time. Is it worth using / possible to effectively use a slower growth rate to lower the initial top bound? e.g. if we could grow by 1.5x, we'd expect a huge win in reducing the cost of the descent part of the algorithm. We should have time to spend on walking up a bit more slowly. Is there some different scheme that would let us ascend some fraction of the way rather than doubling the index every time?&lt;/p&gt;
&lt;h2 id=&quot;why-care&quot;&gt;Why Care?&lt;/h2&gt;
&lt;p&gt;This is a biased search algorithm, after all.&lt;/p&gt;
&lt;p&gt;Well, if our predicate spends a lot of time rummaging around inside of arrays, we know &lt;a href=&quot;http://www.pvk.ca/Blog/2012/07/30/binary-search-is-a-pathological-case-for-caches/&quot;&gt;binary search is a pathological case for caches&lt;/a&gt;. Paul Khuong showed that a traditional binary search if you had a power of 2 worth of elements was pretty awful in terms of its use of the &lt;em&gt;k&lt;/em&gt;-way set associative caches we actually have in our CPUs and that at the very least you should bias your search. Here we're able to skew a little more for little effort. This argument winds up resoundingly similar to the case made by Gerth Stølting Brodal in the paper I linked last time about skewed binary trees, but for different reasons.&lt;/p&gt;
&lt;p&gt;But even if we aren't rummaging through an array, there are some benefits to Fibonacci search. In the implementation above, I put the smaller tree on the left, so it will tend to favor checking smaller elements. If the cost of testing the predicate on a larger number is higher than testing it on a smaller number, then this biases in the correct direction.&lt;/p&gt;
&lt;p&gt;Compared to an open-ended binary search, open-ended Fibonacci search tries to test smaller numbers with lower dispersion in a biased fashion in exchange for testing more numbers, but we're starting to see that this can be a good thing.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;April 27, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/fibonacci-search/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Some Rough Notes on Univalent Foundations and B-Systems, Part I</title><link>https://comonad.com/reader/2015/some-rough-notes-on-univalent-foundations-and-b-systems-part-i/</link><guid isPermaLink="false">https://comonad.com/reader/2015/some-rough-notes-on-univalent-foundations-and-b-systems-part-i/</guid><pubDate>Tue, 15 Sep 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 15 September 2015&lt;/p&gt;&lt;span id=&quot;more-1105&quot;&gt;&lt;/span&gt;&lt;p&gt;I recently attended &lt;a href=&quot;http://rdp15.mimuw.edu.pl/&quot;&gt;RDP&lt;/a&gt; in Warsaw, where there was quite a bit of work on Homotopy Type Theory, including a special workshop organized to present recent and ongoing work. The organizers of all the events did a fantastic job and there was a great deal of exciting work. I should add that I will not be able to go to RDP next year, as the two constituent central conferences (RTA — Rewriting Techniques and Applications and TLCA — Typed Lambda Calculus and Applications) have merged and changed names. Next year it will now be called FSCD — Formal Structures for Computation and Deduction. So I very much look forward to attending FSCD instead.&lt;/p&gt;
&lt;p&gt;In any case, one of the invited speakers was Vladimir Voevodsky, who gave an invited talk on his recent work relating to univalent foundations titled &quot;From Syntax to Semantics of Dependent Type Theories — Formalized”. This was a very clear talk that helped me understand his current research direction and the motivations for it. I also had the benefit of some very useful conversations with others involved in collaboration with some of this work, who patiently answered my questions. The notes below are complimentary to the &lt;a href=&quot;http://hott-uf.gforge.inria.fr/HOTTUF_Vladimir.pdf&quot;&gt;slides from his talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I had sort of understood what the motivation for studying “C-Systems” was, but I had not taken it on myself to look at Voevodsky’s &lt;a href=&quot;http://arxiv.org/abs/1410.5389&quot;&gt;“B-Systems&lt;/a&gt;” before, nor had I grasped how his research programme fit together. Since I found this experience enlightening, I figured I might as well write up what I think I understand, with all the usual caveats. Also note, in all the below, by “type theory” I invariably mean the intensional sort. So all the following is in reference to the B-systems paper that Voevodsky has posted on arXiv (&lt;a href=&quot;http://arxiv.org/abs/1410.5389&quot;&gt;arXiv:1410.5389&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;That said, if anything I describe here strikes you as funny, it is more likely that I am not describing things right than that the source material is troublesome — i.e. take this with a grain of salt. And bear in mind that I am not attempting to directly paraphrase Voevodsky himself or others I spoke to, but rather I am giving an account of where what they described resonated with me, and filtered through my own examples, etc. Also, if all of the “why and wherefore” is already familiar to you, feel free to skip directly to the “B-Systems” section where I will just discuss Voevodsky’s paper on this topic, and my attempts to understand portions of it. And if you already understand B-Systems, please do reply and explain all the things I’m sure I’m missing!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some Review&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We have a model of type theory in simiplicial sets that validates the univalence axiom (and now a few other models that validate this axiom as well). This is to say, it is a model with not only higher dimensional structure, but higher structure of a very “coherent” sort. The heart of this relates to our construction of a “universe”. In our categorical model, all our types translate into objects of various sorts. The “universe,” aka the type-of-types, translates into a very special object, one which “indexes” all other objects. A more categorical way of saying this is that all other types are “fibered over” the universe — i.e. that from every other type there is a map back to a specific point within the universe. The univalence axiom can be read as saying that all equivalent types are fibered over points in the universe that are connected (i.e. there is a path between those points).&lt;/p&gt;
&lt;p&gt;Even in a relatively simple dependent type theory, equivalence of types quickly becomes undecidable in general, as it is a superset of the problem of deciding type inhabitation, which in turn corresponds to the decidability of propositions in the logic corresponding to a type theory, and then by any number of well-known results cannot be resolved in general for most interesting theories. This in turn means that the structure of a univalent universe is “describable” but it is not fully enumerable, and is very complex.&lt;/p&gt;
&lt;p&gt;We also have a line of work dating back to before the introduction of univalence, which investigated the higher groupoid structure (or, if you prefer, higher topological structure or quillen model structure) induced by identity types. But without either univalence or higher-inductive types, this higher groupoid structure is unobservable internally. This is to say, models were possible that would send types to things with higher structure, but no particular use would be made of this higher structure. So, such models could potentially be used to demonstrate that certain new axioms were not conservative over the existing theory, but on their own they did not provide ideas about how to extend the theory.&lt;/p&gt;
&lt;p&gt;How to relate this higher groupoid structure to universes? Well, in a universe, one has paths. Without univalence, these are just identity paths. But regardless, we now get a funny “completion” as our identity paths must &lt;em&gt;themselves&lt;/em&gt; be objects in our universe, and so too the paths between them, etc. In models without higher structure, we might say “there is only one path from each object to itself” and then we need not worry too much about this potential explosion of paths at each level. But by enforcing the higher groupoid structure, this means that our universe now blossoms with all the potentially distinct paths at each level. However, with the only way in our syntax to create such “extra paths” as reflexivity, any such path structure in our model remains “latent”, and can be added or removed without any effect.&lt;/p&gt;
&lt;p&gt;The univalence axiom relies on these higher groupoid structures, but it cannot be reduced to them. Rather, in the model, we must have a fibration over the universe with identity lifting along this fibration to reach the next step — to then modify the universe by forcing paths other than identity paths — those between equivalent types. This is in a sense a further “higher completion” of our universe, adding in first all the possible paths between types, but then the paths between those paths, and so on up. Because, by univalence, we &lt;em&gt;can&lt;/em&gt; state such paths, then in our model we &lt;em&gt;must&lt;/em&gt; include all&lt;br&gt;
of them.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;All along I have been saying “models of type theory”. And it is true enough. We do know how to model type theories of various sorts categorically (i.e. representing the translation from their syntax into their semantics as functorial). But we do not have full models of &quot;fully-featured&quot; type theories; i.e. if we view type theories as pizzas we have models of cheese slices, and perhaps slices with olives and slices with pepperoni, etc. But we do not have models of pizzas with &quot;all the toppings&quot;. Here, by &quot;toppings&quot; I mean things such as the addition of &quot;all inductive types,&quot; &quot;some coinductive types,&quot; &quot;certain higher-inductive types,&quot; &quot;pattern matching,&quot; &quot;induction-induction,&quot; &quot;induction-recursion,&quot; &quot;excluded middle as an axiom,&quot; &quot;choice as an axiom,&quot; &quot;propositional resizing as an axiom,&quot; etc.&lt;/p&gt;
&lt;p&gt;Rather, we have a grab bag of tricks, as well as a few slightly different approaches — Categories with Attributes, Categories with Families, and so forth. One peculiar feature of these sorts of models, as opposed to the models of extensional type theory, is that these models are not indexed by types, but by “lists of types” that directly correspond to the contexts in which we make typing judgments in intensional theories.&lt;/p&gt;
&lt;p&gt;In any case, these models are usually used in an ad-hoc fashion. If you want to examine a particular feature of a language, you first pick from one of these different but related sorts of models. Then you go on to build a version with the minimal set of what you need — so maybe identity types, maybe sigma types, maybe natural numbers, and then you introduce your new construction or generate your result or the like.&lt;/p&gt;
&lt;p&gt;So people may say “we know how to work with these things, and we know the tricks, so given a theory, we can throw together the facts about it pretty quickly.” Now of course there are maybe only a hundred people on the planet (myself not among them) who can &lt;em&gt;really&lt;/em&gt; just throw together a categorical model of some one or another dependent type theory at the drop of a hat.&lt;/p&gt;
&lt;p&gt;But there’s a broader problem. How can we speak about the mutual compatibility of different extensions and features if each one is validated independently in a different way? This is a problem very familiar to us in the field of programming languages — you have a lot of “improvements” to your language, all of a similar form. But then you put such “improvements” together and now something goes wrong. In fact, the famous “newtype deriving bug” in GHC some years back, which opened a big hole in the type system, was of exactly that form — two extensions (in that case, newtype deriving and type families) that are on their own safe and useful, together have an unexpected bad effect. It is also possible to imagine bad interactions occuring only when three extensions exist together, and soforth. So as the number of extensions increases, the number of interactions to check spirals upwards in a very difficult fashion.&lt;/p&gt;
&lt;p&gt;So the correct way to have confidence in the coexistence of these various extensions is to have a general model that contains the sort of theory we actually want to work in, rather than these toy theories that let us look at portions in isolation. And this certainly involves having a theory that lets us validate all inductive types at once in the model, rather than extending it over and over for each new type we add. Additionally, people tend to model things with at most one universe. And when we are not looking at universes, it is often omitted altogether, or done “incorrectly” as an inhabitant of itself, purely for the sake of convenience.&lt;/p&gt;
&lt;p&gt;So now, if I tell someone with mathematical experience what my theory “means” and they say “is this actually proven” I’m in the embarrassing position of saying “no, it is not. but the important bits all are and we know how to put them together.” So here I am, trying to advocate the idea of fully formal verification, but without a fully top-to-bottom formally verified system myself — not even codewise, but in even the basic mathematical sense.&lt;/p&gt;
&lt;p&gt;Univalence makes this problem more urgent. Without univalence, we can often get away with more hand-wavy arguments, because things are “obvious”. Furthermore, they relate to the way things are done elsewhere. So logic can be believed by analogy to how people usually think about logic, numbers by analogy to the peano system, which people already “believe in,” and soforth. Furthermore, without univalence, most operations are “directly constructive” in the sense that you can pick your favorite “obvious” and non-categorical model, and they will tend to hold in that as well — so you can think of your types as sets, and terms as elements of sets. Or you can think of your types as classifying computer programs and your terms as runnable code, etc. In each case, the behavior leads to basically what you would expect.&lt;/p&gt;
&lt;p&gt;But in none of these “obvious” models does univalence hold. And furthermore, it is “obviously” wrong in them.&lt;/p&gt;
&lt;p&gt;And that is just on the “propaganda” side as people say. For the same reasons, univalence tends to be incompatible with many “obvious” extensions — for example, not only “uniqueness of identity proofs” has to go, but pattern matching had to be rethought so as not to imply it, and furthermore it is not known if it is sound in concert with many other extensions such as general coinductive types, etc. (In fact, the newtype deriving bug itself can be seen as a &quot;very special case&quot; of the incompatibility of univalence with Uniqueness of Identity Proofs, as I have been discussing with people informally for quite some time).&lt;/p&gt;
&lt;p&gt;Hence, because univalence interacts with so many other extensions, it feels even more urgent to have a full account. Unlike prior research, which really focused on developing and understanding type systems, this is more of an engineering problem, although a proof-engineering problem to be sure.&lt;/p&gt;
&lt;h2 id=&quot;the-approach&quot;&gt;The Approach&lt;/h2&gt;
&lt;p&gt;Rather than just giving a full account of “one important type system,” Voevodsky seems to be aiming for a generally smooth way to develop such full accounts even as type systems change. So he is interested in reusable technology, so to speak. One analogy may be that he is interested in building the categorical semantics version of a logical framework. His tool for doing this is what he calls a “&lt;a href=&quot;http://arxiv.org/abs/1410.5389&quot;&gt;C-system&lt;/a&gt;”, which is a slight variant of Cartmell’s Categories with Attributes mentioned above. One important aspect of C-systems seems to be that that they stratify types and terms in some fashion, and that you can see them as generated by some “data” about a ground set of types, terms, and relations. To be honest, I haven’t looked at them more closely than that, since I saw at least some of the “point” of them and know that to really understand the details I'll have to study categorical semantics more generally, which is ongoing.&lt;/p&gt;
&lt;p&gt;But the plan isn’t just to have a suitable categorical model of type theories. Rather it is to give a description of how one goes from the “raw terms” as syntax trees all the way through to how typing judgments are passed on them and then to their full elaborations in contexts and finally to their eventual “meaning” as categorically presented.&lt;/p&gt;
&lt;p&gt;Of course, most of these elements are well studied already, as are their interactions. But they do not live in a particularly compatible formulation with categorical semantics. This then makes it difficult to prove that “all the pieces line up” and in particular, a pain to prove that a given categorical semantics for a given syntax is the “initial” one — i.e. that if there is any other semantics for that syntax, it can be arrived at by first “factoring through” the morphism from syntax to the initial semantics. Such proofs can be executed, but again it would be good to have “reusable technology” to carry them out in general.&lt;/p&gt;
&lt;h2 id=&quot;pre-b-systems&quot;&gt;pre-B-Systems&lt;/h2&gt;
&lt;p&gt;Now we move into the proper notes on &lt;a href=&quot;http://arxiv.org/abs/1410.5389&quot;&gt;Voevodsky's &quot;B-Systems&quot; paper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If C-systems are at the end-point of the conveyor belt, we need the pieces in the middle. And that is what a B-system is. Continuing the analogy with the conveyor belt, what we get out at the end is a “finished piece” — so an object in a C-system is a categorified version of a “type in-context” capturing the “indexing” or “fibration” of that type over its “base space” of types it may depend on, and also capturing the families of terms that may be formed in various different contexts of other terms with other types.&lt;/p&gt;
&lt;p&gt;B-systems, which are a more “syntactic” presentation, have a very direct notion of “dynamics” built in — they describe how objects and contexts may be combined and put together, and directly give, by their laws, which slots fit into which tabs, etc. Furthermore, B-systems are to be built by equipping simpler systems with successively more structure. This gives us a certain sort of notion of how to talk about the distinction between things closer to &quot;raw syntax&quot; (not imbued with any particular meaning) and that subset of raw syntactic structures which have certain specified actions.&lt;/p&gt;
&lt;p&gt;So enough prelude. What precisely is a B-system? We start with a pre-B-system, as described below (corresponding to Definition 2.1 in the paper).&lt;/p&gt;
&lt;p&gt;First there is a family of sets, indexed by the natural numbers. We call it &lt;code&gt;B_n&lt;/code&gt;. &lt;code&gt;B_0&lt;/code&gt; is to be thought of as the empty context. &lt;code&gt;B_1&lt;/code&gt; as the set of typing contexts with one element, &lt;code&gt;B_2&lt;/code&gt; as the set with two elements, where the second may be indexed over the first, etc. Elements of &lt;code&gt;B_3&lt;/code&gt; thus can be thought of as looking like &quot;&lt;code&gt;x_1 : T_1, x_2 : T_2(x_1), x_3 : T_3(x_1,x_2)&lt;/code&gt;&quot; where &lt;code&gt;T_2&lt;/code&gt; is a type family over one type, &lt;code&gt;T_3&lt;/code&gt; a type family over two types, etc.&lt;/p&gt;
&lt;p&gt;For all typing contexts of at least one element, we can also interpret them as simply the _type_ of their last element, but as indexed by the types of all their prior elements. Conceptually, &lt;code&gt;B_n&lt;/code&gt; is the set of &quot;types in context, with no more than n-1 dependencies&quot;.&lt;/p&gt;
&lt;p&gt;Now, we introduce another family of sets, indexed by the natural numbers starting at 1. We call this set &lt;code&gt;˜B_n&lt;/code&gt;. &lt;code&gt;˜B_1&lt;/code&gt; is to be thought of as the set of all values that may be drawn from any type in the set B_1, and soforth. Thus, each set &lt;code&gt;˜B_n&lt;/code&gt; is to be thought of as fibered over &lt;code&gt;B_n&lt;/code&gt;. We think of this as &quot;terms in context, whose types have no more than n-1 dependencies&quot;. Elements of &lt;code&gt;˜B_3&lt;/code&gt; can be though of as looking like &quot;&lt;code&gt;x_1 : T_1, x_2 : T_2(x_1), x_3 : T_3(x_1,x_2) ⊢ y : x&lt;/code&gt;&quot;. That is to say, elements of &lt;code&gt;B_n&lt;/code&gt; for some n look like &quot;everything to the left of the turnstile&quot; and elements of ˜B_n for some n look like &quot;the left and right hand sides of the turnstile together.&quot;&lt;/p&gt;
&lt;p&gt;We now, for each n, give a map:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;∂ : ˜B_n+1 -&amp;gt; B_n+1.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This map is the witness to this fibration. Conceptually, it says &quot;give me an element of some type of dependency level n, and I will pick out which type this is an element of&quot;. We can call ∂ the &quot;type of&quot; operator.&lt;/p&gt;
&lt;p&gt;We add a second basic map:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ft : B_n+1 -&amp;gt; B_n&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is a witness to the fact that all our higher &lt;code&gt;B_n&lt;/code&gt; are built as extensions of smaller ones. It says &quot;Give me a context, and I will give you the smaller context that has every element except the final one&quot;. Alternately, it reads &quot;Give me a type indexed over a context, and I will throw away the type and give back just the context.&quot; Or, &quot;Give me a type that may depend on n+1 things, and I will give the type it depends on that may only depend on n things. We can call ft the &quot;context of&quot; operator.&lt;/p&gt;
&lt;p&gt;Finally, we add a number of maps to correspond to weakening and substitution -- four in all. In each case, we take m &amp;gt;= n. we denote the i-fold application of &lt;code&gt;ft&lt;/code&gt; by &lt;code&gt;ft_i&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;T (type weakening).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;T : (Y : B_n+1) -&amp;gt; (X : B_m+1) -&amp;gt; ft(Y) = ft_(m+1-n)(X) -&amp;gt; B_m+2   &lt;/code&gt;&lt;br&gt;
This reads: Give me two types-in-context, X and Y. Now, if the context for Y agrees with the context for X in the initial segment (i.e. discarding the elements of the context of X which are &quot;longer&quot; than the context for Y), then I can give you back X again, but now in an extended context that includes Y as well.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;˜T (term weakening).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;˜T : (Y : B_n+1) -&amp;gt; (r : ˜B_m+1) -&amp;gt; ft(Y)=ft_(m+1-n)(∂(r)) -&amp;gt; ˜B_m+2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This reads: Give me a type-in-context Y, and a term-in-context r. Now, if the context of Y agrees with the context for the type of r as above, then I can give you back r again, but now as a term-in-context whose type has an extended context that includes Y as well.&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;S (type substitution).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;S : (s : ˜B_n+1) -&amp;gt; (X : B_m+2) -&amp;gt; ∂(s) = ft_(m+1-n)(X) -&amp;gt; B_m+1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This reads: give me a term-in-context s, and a type-in-context X. Now, if the context of the type of s agrees with the context of the X in the initial segment, we may then produce a new type, which is X with one less element in its context (because we have substituted the explicit term s for where the prior dependency data was recorded).&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;˜S (term substitution).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;˜S : (s : ˜B_n+1) -&amp;gt; (r : ˜B_m+2) -&amp;gt; ∂(s) = ft_(m+1-n)(∂(r)) -&amp;gt; ˜B_m+1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This reads: give me two terms-in-context, r and s. Now given the usual compatibility condition on contexts, we can produce a new term, which is like r, but where the context has one less dependency (because we have substituted the explicit term s for everywhere where there was dependency data prior).&lt;/p&gt;
&lt;p&gt;Let us now review what we have: We have dependent terms and types, related by explicit maps between them. For every term we have its type, and for every type we have its context. Furthermore, we have weakening by types of types and terms -- so we record where &quot;extra types&quot; may be introduced into contexts without harm. We also have substitution of terms into type and terms -- so we record where reductions may take place, and the resulting effect on the dependency structure.&lt;/p&gt;
&lt;h2 id=&quot;unital-pre-b-systems&quot;&gt;Unital pre-B-systems&lt;/h2&gt;
&lt;p&gt;We now introduce a further piece of data, which renders a pre-B-system a _unital_ pre-B-system, corresponding to Definition 2.2 in the paper. For each n we add an operation:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;δ : B_n+1 -&amp;gt; ˜B_n+2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This map &quot;turns a context into a term&quot;. Conceptually it is the step that equips a pre-B-system with a universe, as it is what allows types to transform into terms. I find the general definition a bit confusing, but I believe it can be rendered syntactically for for B_2, it can be as something like the following: &quot;&lt;code&gt;x_1 : T_1, x_2 : T_2(x_1) -&amp;gt; x_1 : T_1, x_2 : T_2(x_1), x_3 : U ⊢ x_2 : x_3&lt;/code&gt;&quot;. That is to say, given any context, we now have a universe &lt;code&gt;U&lt;/code&gt; that gives the type of &quot;universes of types&quot;, and we say that the type itself is a term that is an element of a universe. Informally, one can think of &lt;code&gt;δ&lt;/code&gt; as the &quot;term of&quot; operator.&lt;/p&gt;
&lt;p&gt;But this specific structure is not indicated by any laws yet on δ. Indeed, the next thing we do is to introduce a &quot;B0-system&quot; which adds some further coherence conditions to restrict this generality.&lt;/p&gt;
&lt;h2 id=&quot;b0-systems&quot;&gt;B0-systems&lt;/h2&gt;
&lt;p&gt;The following are my attempt to &quot;verbalize&quot; the B0 system conditions (as restrictions on non-unital pre-B-systems) as covered in definition 2.5. I do not reproduce here the actual formal statements of these conditions, for which one should refer to the paper and just reason through very carefully.&lt;/p&gt;
&lt;p&gt;1. The context of a weakening of a type is the same as the weakening of the context of a type.&lt;/p&gt;
&lt;p&gt;2. The type of the weakening of a term is the same as the weakening of the type of a term.&lt;/p&gt;
&lt;p&gt;3. The context of a substitution into a type is the same as the substitution into a context of a type&lt;/p&gt;
&lt;p&gt;4. The type of a substitution into a term is the same as a substitution into the type of a term.&lt;/p&gt;
&lt;p&gt;Finally, we &quot;upgrade&quot; a non-unital B0-system to a unital B0-system with one further condition:&lt;/p&gt;
&lt;p&gt;5. &lt;code&gt;∂(δ(X)) =T(X,X).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I read this to say that, &quot;for any type-in-context X, the type of the term of X is the same as the weakening of the context of X by the assumption of X itself.&quot; This is to say, if I create a term for some type X, and then discard that term, this is the same as extending the context of X by X again.&lt;/p&gt;
&lt;p&gt;Here, I have not even gotten to &quot;full&quot; B-systems yet, and am only on page 5 of a seventeen page paper. But I have been poking at these notes for long enough without posting them, so I'll leave off for now, and hopefully, possibly, when time permits, return to at least the second half of section 2.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/some-rough-notes-on-univalent-foundations-and-b-systems-part-i/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>On-line Lowest Common Ancestor</title><link>https://comonad.com/reader/2015/online-lca/</link><guid isPermaLink="false">https://comonad.com/reader/2015/online-lca/</guid><pubDate>Thu, 27 Aug 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 27 August 2015&lt;/p&gt;&lt;p&gt;On-line &lt;a href=&quot;http://en.wikipedia.org/wiki/Lowest_common_ancestor&quot;&gt;lowest common ancestor&lt;/a&gt; (LCA) search and the on-line version of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Level_ancestor_problem&quot;&gt;level ancestor problem&lt;/a&gt; have been traditionally viewed as having &lt;em&gt;O(h)&lt;/em&gt; solutions.&lt;/p&gt;
&lt;p&gt;Last year, I improved both of those bounds to &lt;em&gt;O(log h)&lt;/em&gt; while using only purely functional data structures, when I was working on another problem, and I figured I should do a write-up on how that worked, as I'm going to use some of the same componentry in future posts.&lt;/p&gt;
&lt;p&gt;Like most of my posts of late this one will dip a little bit into how we can use this abstruse theory to get improved distribution and parallelism as well.&lt;/p&gt;
&lt;p&gt;In future posts, I'll talk about how this can be used to derive an efficient revision control monad and I've been using the same skew binary arithmetic to derive an efficient cache-oblivious unboxable version of the venerable &lt;code&gt;Data.Map&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lowest-common-ancestor&quot;&gt;Lowest Common Ancestor&lt;/h2&gt;
&lt;p&gt;Given a tree and two nodes in the tree, find the lowest entry in the tree that is an ancestor to both.&lt;/p&gt;
&lt;p&gt;Consider this tree:&lt;/p&gt;
&lt;img alt=&quot;Illustration from On-line Lowest Common Ancestor&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/314613275adb-lca-example-1.png&quot;&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;I&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;H&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;J&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There has been a lot written about the version of this problem, where there tree is fixed and unchanging, but not much about it in the case where it is allowed to continue to evolve.&lt;/p&gt;
&lt;p&gt;There are a lot of applications for LCA.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Computing dominators in flow graphs&lt;/li&gt;
&lt;li&gt;Three-Way merge algorithms&lt;/li&gt;
&lt;li&gt;Finding common word roots/suffixes&lt;/li&gt;
&lt;li&gt;Range-Min Query (RMQ) problems&lt;/li&gt;
&lt;li&gt;Computing distances in a tree&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://dl.acm.org/citation.cfm?id=804056&quot;&gt;Aho, Hopcraft and Ullman&lt;/a&gt; originally formulated the lowest common ancestor problem 40 years ago, back in 1973.&lt;/p&gt;
&lt;p&gt;They provided both on-line and off-line versions of the problem, defined around two operations &lt;code&gt;link&lt;/code&gt; and &lt;code&gt;lca&lt;/code&gt;, but their specification has a distinctly imperative flavor.&lt;/p&gt;
&lt;p&gt;LCA was defined in terms of two operations &lt;code&gt;link x y&lt;/code&gt; and &lt;code&gt;lca x y&lt;/code&gt;. &lt;code&gt;link x y&lt;/code&gt; grafts an &quot;unattached tree&quot; &lt;code&gt;x&lt;/code&gt; on as a new child of &lt;code&gt;y&lt;/code&gt;, while &lt;code&gt;lca x y&lt;/code&gt; computes the lowest common ancestor of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The difference betwen on-line and off-line has classically been whether the set of &lt;code&gt;link&lt;/code&gt; and &lt;code&gt;lca&lt;/code&gt; commands was fixed a priori.&lt;/p&gt;
&lt;p&gt;Research has largely focused on the slightly more permissive off-line version of the problem where you are given the entire tree &lt;em&gt;a priori&lt;/em&gt;. The original off-line version of the algorithm required time &lt;em&gt;O(n log* n)&lt;/em&gt; for a precanned set of &lt;code&gt;lca&lt;/code&gt; and &lt;code&gt;link&lt;/code&gt; operations, and their on-line version required &lt;em&gt;O(n log n)&lt;/em&gt;. These have since been improved.&lt;/p&gt;
&lt;h3 id=&quot;off-line-lca&quot;&gt;Off-line LCA&lt;/h3&gt;
&lt;p&gt;In general, these days if you're able to set up the tree you want in advance, and are willing to spend &lt;code&gt;O(n)&lt;/code&gt; time preprocessing it, then you can answer subsequent &lt;code&gt;lca&lt;/code&gt; queries on it in &lt;code&gt;O(1)&lt;/code&gt;! However, if you make &lt;em&gt;any&lt;/em&gt; edits, then you have to reprocess the entire tree in &lt;code&gt;O(n)&lt;/code&gt; time. This renders these algorithms unsuitable for things like computing LCAs in version control graphs.&lt;/p&gt;
&lt;p&gt;These algorithms are actually pretty complicated. They involve tricks like round-tripping to and from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Range_Minimum_Query&quot;&gt;Range-Minimum-Query&lt;/a&gt; (RMQ) formulation twice.&lt;/p&gt;
&lt;p&gt;There is &lt;a href=&quot;http://community.topcoder.com/tc?module=Static&amp;d1=tutorials&amp;d2=lowestCommonAncestor&quot;&gt;an excellent writeup&lt;/a&gt; that covers these classical techniques on this on top-coder. In the notation used there, the solution I'm going to explore is &lt;code&gt;&amp;lt;O(1),O(log H)&amp;gt;&lt;/code&gt;, where &lt;code&gt;H&lt;/code&gt; is the height of the tree, not the full size &lt;code&gt;N&lt;/code&gt; that has to be used for all the other algorithms explored.&lt;/p&gt;
&lt;h3 id=&quot;functional-lca&quot;&gt;Functional LCA&lt;/h3&gt;
&lt;p&gt;Notice in Aho, Hopcraft and Ullman's specification, &lt;code&gt;link&lt;/code&gt; doesn't return anything! It is an inherently mutation-oriented approach to the problem statement. Instead I'm going to replace &lt;code&gt;link x y&lt;/code&gt; with &lt;code&gt;cons a y&lt;/code&gt;, which returns a new extended version of the path &lt;code&gt;y&lt;/code&gt;, grown downward with the new &lt;em&gt;globally unique&lt;/em&gt; node ID &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We could also choose to replace &lt;code&gt;cons a y&lt;/code&gt; with a monadic &lt;code&gt;grow y&lt;/code&gt;, which tracks some kind of variable supply internally. By using a concurrent variable supply like the one in my &lt;a href=&quot;https://hackage.haskell.org/package/concurrent-supply&quot;&gt;&lt;code&gt;concurrent-supply&lt;/code&gt; package&lt;/a&gt;, we can grow the tree in parallel across multiple cores.&lt;/p&gt;
&lt;h3 id=&quot;the-dumbest-thing-that-could-work&quot;&gt;The Dumbest Thing That Could Work&lt;/h3&gt;
&lt;p&gt;We can define a path to be just a a list with an associated length.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; = [&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;] :# !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can build them up:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; = [] :# &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a (ys :# n) = (a:ys) :# (n + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that paths look like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = [&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] :# &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt; =   [&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] :# &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can compute the lowest common ancestor of two paths by just cutting them off at the same height and marching down them in lock-step, comparing for equality as we go.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;x'&lt;/span&gt; = [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] :# &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;y'&lt;/span&gt; = [&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] :# &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; x y = [&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] :# &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Scribbling that out we get this algorithm.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; (xs0 :# i) (ys0 :# j) = go k (drop (i-k) xs0) (drop (j-k) ys0) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k = min i j
  go !n xxs@(x:xs) (y:ys)
    | x == y   = xxs :# n
    | otherwse = go (n - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) xs ys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Already it has a number of pros and cons.&lt;/p&gt;
&lt;p&gt;1.) It requires no preprocessing step.&lt;/p&gt;
&lt;p&gt;2.) It is only &lt;em&gt;O(1)&lt;/em&gt; to extend a path, and did I mention there is no recomputation necessary?&lt;/p&gt;
&lt;p&gt;3.) There is no need to store the entire tree! You only ever have to store the paths you are actively considering. This helps with distribution and parallelization.&lt;/p&gt;
&lt;p&gt;4.) On one hand, it is &lt;em&gt;O(h)&lt;/em&gt; in the height &lt;code&gt;h&lt;/code&gt; of our tree to compute and this is bad in that &lt;em&gt;O(h)&lt;/em&gt; is a lot more than the &lt;em&gt;O(1)&lt;/em&gt; &lt;code&gt;lca&lt;/code&gt; calculations of the standard toolbox.&lt;/p&gt;
&lt;p&gt;5.) On the other hand, &lt;em&gt;O(h)&lt;/em&gt; is still often a lot less than a full &lt;em&gt;O(n)&lt;/em&gt; recalculation required by other approaches as your tree changes. This permits the use of this algorithm when we care about on-line edits being made to the tree, and where we need to be able to roll with the punches rather than stop the world for a single calculation.&lt;/p&gt;
&lt;p&gt;The bottleneck here is obviously the suffix extraction. It takes potentially &lt;em&gt;O(h)&lt;/em&gt; to trim the two lists to the same length, then it takes &lt;em&gt;O(h)&lt;/em&gt; to scan the trimmed lists in parallel.&lt;/p&gt;
&lt;p&gt;As is usually my wont, I'll turn to Okasaki for at least part of the answer.&lt;/p&gt;
&lt;h2 id=&quot;types-from-number-systems&quot;&gt;Types from Number Systems&lt;/h2&gt;
&lt;p&gt;One tool in the functional programming tool-box is the trick of turning a number system into a data structure.&lt;/p&gt;
&lt;h3 id=&quot;unary&quot;&gt;Unary&lt;/h3&gt;
&lt;p&gt;We're actually quite familiar with one such structure:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;    = &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;    &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IdList&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;  | &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IdList&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we can think of &lt;code&gt;Nat&lt;/code&gt; as a unary encoding of the natural numbers. (Technically they are extended here via their one-point compactification with infinity due to laziness.)&lt;/p&gt;
&lt;p&gt;If we augment each &lt;code&gt;Succ&lt;/code&gt; with a piece of data, this gives us the well known list data structure.&lt;/p&gt;
&lt;p&gt;Here the fact that we can increment a unary number in &lt;em&gt;O(1)&lt;/em&gt; leads to the observation that we can &lt;code&gt;cons&lt;/code&gt; onto our list in &lt;em&gt;O(1)&lt;/em&gt; as well.&lt;/p&gt;
&lt;p&gt;The cost of adding numbers in unary and the costs of appending lists are related as well.&lt;/p&gt;
&lt;p&gt;The asymptotics of &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt; can be related to the complexity of calculating similar clamped operations involving &lt;code&gt;min&lt;/code&gt; on the naturals.&lt;/p&gt;
&lt;h3 id=&quot;binary&quot;&gt;Binary&lt;/h3&gt;
&lt;p&gt;It worked with unary, so we could try to do this with binary, but it wouldn't work well. We could use a bunch of arrays with sizes based on powers of 2, where each array is present or absent such that the total of all of the array sizes is our number of elements, but when we're done we'd still have to do a bunch of array merging. Incrementing our counter may cause a 'carry' that affects all &lt;em&gt;O(log n)&lt;/em&gt; such arrays!&lt;/p&gt;
&lt;p&gt;This leads us to search for a number system where carries lead to less work.&lt;/p&gt;
&lt;h3 id=&quot;skew-binary&quot;&gt;Skew Binary&lt;/h3&gt;
&lt;p&gt;Skew Binary is a type of &quot;almost binary&quot; number system, where our digits are either 0 or 1... or 2.&lt;/p&gt;
&lt;p&gt;It differs from ternary in the value of eachdigits, and in the fact that we're only going to allow ourselves at most a single 2, and we'll use it to defeat the need for multiple carries.&lt;/p&gt;
&lt;p&gt;In skew binary, the _n_th digit is worth 2^(k+1)-1, rather than 2^k like in binary.&lt;/p&gt;
&lt;p&gt;This leads to the progression:&lt;/p&gt;
&lt;p&gt;1,3,7,15,31,63,127...&lt;/p&gt;
&lt;p&gt;rather than the binary progression so familiar to programmers.&lt;/p&gt;
&lt;p&gt;1,2,4,8,16,32,64...&lt;/p&gt;
&lt;p&gt;If we say the &lt;code&gt;2&lt;/code&gt; can only occur as the least significant non-zero in our number, then every natural can be &lt;em&gt;uniquely&lt;/em&gt; represented in skew binary. We'll need this uniqueness later!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;n     731                      n
--    ---                      --
 0:   000 --                    0
 1:   001 --             1*1 =  1
 2:   002 --             2*1 =  2
 3:   010 --       1*3       =  3
 4:   011 --       1*3 + 1*1 =  4
 5:   012 --       1*3 + 2*1 =  5
 6:   020 --       2*3       =  6
 7:   100 -- 1*7             =  7
 8:   101 -- 1*7    +    1*1 =  8
 9:   102 -- 1*7    +    2*1 =  9
10:   110 -- 1*7 + 1*3       = 10
11:   111 -- 1*7 + 1*3 + 1*1 = 11
12:   112 -- 1*7 + 1*3 + 2*1 = 12
13:   120 -- 1*7 + 2*3       = 13
14:   200 -- 2*7             = 14
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we represent a skew binary number as a linked list of digits from least to most significant, such that we just don't store the zeros and just store the number of inhabitants by storing the size we can write:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Two&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By inspection, incrementing the counter is an &lt;code&gt;O(1)&lt;/code&gt; operation, (if we ignore the price of manipulating the size).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Two&lt;/span&gt; x (&lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; y ys)) | x*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; == y = &lt;span class=&quot;hljs-type&quot;&gt;Two&lt;/span&gt; y ys
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Two&lt;/span&gt; x xs) = &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; (x*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) xs
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; xs) = &lt;span class=&quot;hljs-type&quot;&gt;Two&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; xs
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; xs         = &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can greatly simplify this by just saying that a 'Two' is really two ones of the same size in a list. Due to our constraints, such a &lt;code&gt;Two&lt;/code&gt; will only occur at the front of the list.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can observe that &lt;code&gt;Skew&lt;/code&gt; is just &lt;code&gt;[Int]&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; = [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;]&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skew&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; (x:y:zs) | x == y = x+y+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; : zs
&lt;span class=&quot;hljs-title&quot;&gt;succ&lt;/span&gt; xs = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what happens when we turn this into a data structure?&lt;/p&gt;
&lt;p&gt;Now all we want to do is replace our digits with a data structure that has the same size. Our digits are sized like: 1,3,7,15... Those look familiar. That is the number of children in complete binary trees of a heights 1,2,3,4...&lt;/p&gt;
&lt;p&gt;If only we had some operation that took one element, and two complete binary trees and gave us a new binary tree, like making that element the new root...&lt;/p&gt;
&lt;p&gt;We could get fancy and enforce the completeness of these trees bottom up
or top down with invariants, but I leave that to you to do efficiently.&lt;/p&gt;
&lt;p&gt;We'll need a size as well, so let's shoehorn that in too.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; _) = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; n _ _ _) = n
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; = [&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Corresponding to &lt;code&gt;succ&lt;/code&gt;, we could now implement &lt;code&gt;cons&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a (x:y:zs) | size x == size y = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (size x*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) a x y : zs
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a xs = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a : xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we've done is maintain the invariant that a &quot;digit&quot; worth &lt;code&gt;n&lt;/code&gt; is associated with &lt;code&gt;n&lt;/code&gt; entries worth of data.&lt;/p&gt;
&lt;p&gt;With that &lt;code&gt;cons&lt;/code&gt; for our paths is now &lt;code&gt;O(1)&lt;/code&gt;. You can similarly generate &lt;code&gt;pred&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cleaning-up&quot;&gt;Cleaning Up&lt;/h2&gt;
&lt;p&gt;For sake of convenience I'm going to want to know the total number of elements in the whole list of trees. This is technically a matter of convenience rather than necessity, as it doesn't affect us asymptotically, so let's go back and redefine &lt;code&gt;Path&lt;/code&gt; to be a real data type. While we're at it, we can switch the size annotation to the list node as well, so we don't have to store it recursively in the trees. Finally, I'm going to fix the type of the IDs to &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With those gymnastics out of the way we're left with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- `n` entries in this path&lt;/span&gt;
         !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- `w` entries in this particular tree&lt;/span&gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- a complete tree with @w@ elements&lt;/span&gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now our Trees are storing an &lt;code&gt;Int&lt;/code&gt; key / &lt;code&gt;a&lt;/code&gt; value pair rather than a size and a value:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with a for-internal-use-only helper:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;consT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;consT&lt;/span&gt; w t ts = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (w + size ts) w t ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can define &lt;code&gt;cons&lt;/code&gt; and &lt;code&gt;uncons&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; n w t (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w' t2 ts))
  | w == w' = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (n + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * w + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k t t2) ts
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; k ts = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (size ts + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) ts

&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) ts)     = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (k, ts)
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k l r) ts) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (k, consT w2 l (consT w2 r ts))
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you prefer, you can go implement &lt;code&gt;cons&lt;/code&gt;/&lt;code&gt;uncons&lt;/code&gt; using the &lt;code&gt;_Cons&lt;/code&gt; &lt;code&gt;Prism&lt;/code&gt; from &lt;code&gt;lens&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;This gives us a pretty basic &quot;skew binary random access list&quot; of identifiers.&lt;/p&gt;
&lt;h2 id=&quot;keep-on-trimming&quot;&gt;Keep On Trimming&lt;/h2&gt;
&lt;p&gt;All we need to do is address the &lt;code&gt;O(h)&lt;/code&gt; cost of trimming and the &lt;code&gt;O(h)&lt;/code&gt; cost of scanning.&lt;/p&gt;
&lt;p&gt;Rather than talk about dropping, it is easier to switch to tracking how much we want to &lt;code&gt;keep&lt;/code&gt;. The transformation to the original list code is trivial.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; k (xs :# n) = drop (n-k) xs :# max &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; (n-k)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, now the issue becomes how to define a faster &lt;code&gt;keep&lt;/code&gt; to deal with the trimming.&lt;/p&gt;
&lt;p&gt;To define a faster &lt;code&gt;keep&lt;/code&gt;, we need to work smarter. We have at most &lt;code&gt;O(log h)&lt;/code&gt; trees in our skew binary random access list.&lt;/p&gt;
&lt;p&gt;So we can run along our list of trees until we find the tree we need to cut up to get a skew binary random access list of the right size.&lt;/p&gt;
&lt;p&gt;When we're done, we can just cut off the tops of our tree to keep the right number of entries.&lt;/p&gt;
&lt;p&gt;Consider what happens when we have the &lt;code&gt;Path&lt;/code&gt; of identifiers &lt;code&gt;[6,5,4,3,2,1]&lt;/code&gt; and we want to &lt;code&gt;keep&lt;/code&gt; only the top 2.&lt;/p&gt;
&lt;p&gt;Recall our digits are worth 1,3,7,15..., so since 6 = 2*3, our path would be represented by two complete binary trees each with three elements in them.&lt;/p&gt;
&lt;p&gt;Running down the spine: we see &lt;code&gt;Cons 6 3 tree1 (Cons 3 1 tree2 Nil)&lt;/code&gt;, so we can just drop the first tree wholesale: (Cons 3 1 tree2 Nil), so we know we're going to cut up &lt;code&gt;tree2&lt;/code&gt; to get our new list.&lt;/p&gt;
&lt;img alt=&quot;Illustration from On-line Lowest Common Ancestor&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/c64eac66f308-tree-keeping.gif&quot;&gt;
&lt;p&gt;If we had a bigger structure we'd be getting out new complete trees to cons onto the rest of the list... but recall, later trees are always bigger than ones that came before with the possible exception of the first two trees, and if we cut off the top of a tree, we're going to wind up smaller still.&lt;/p&gt;
&lt;p&gt;Turning that into code:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; k xs@(&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; n w t ts)
  | k &amp;gt;= n = xs
  | otherwise = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k (n - w) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
     &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; keepT (k - n + w) w t ts
     &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; ts
     &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; keep k ts

&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; n w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ l r) ts = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare n w2 &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; keepT n w2 r ts
  &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; consT w2 r ts
  &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; | n == w - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; -&amp;gt; consT w2 l (consT w2 r ts)
     | otherwise -&amp;gt; keepT (n - w2) w2 l (consT w2 r ts)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; _ _ _ ts = ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;keepT&lt;/code&gt; is used when we know we're taking at least one element off the top of a Tree, and that that tree is at most as tall as the shortest tree in a &lt;code&gt;Path&lt;/code&gt;, AND we can know that the path has at most one element of its shorest length, so after we cut off the top, we can at most produce 2 nodes of the same size, but they'll be shorter than everything in the Path.&lt;/p&gt;
&lt;p&gt;Putting all of that together, we can prove &lt;code&gt;keep&lt;/code&gt; takes &lt;code&gt;O(log h)&lt;/code&gt;, but I leave that to you to do to convince yourself.&lt;/p&gt;
&lt;p&gt;The notion that &lt;code&gt;keep&lt;/code&gt; or &lt;code&gt;drop&lt;/code&gt; can be implemented in logarithmic time in a skew binary random access list had previously been unpublished.&lt;/p&gt;
&lt;p&gt;This is sufficient to yield an improvement in the known asymptotics for the on-line version of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Level_ancestor_problem&quot;&gt;level ancestor&lt;/a&gt; problem. Just take your &lt;code&gt;Path&lt;/code&gt; and &lt;code&gt;keep&lt;/code&gt; how ever many levels you want!&lt;/p&gt;
&lt;h2 id=&quot;observations&quot;&gt;Observations&lt;/h2&gt;
&lt;p&gt;To implement a faster &lt;code&gt;trim&lt;/code&gt; we need a few observations on the nature of a skew binary random access list.&lt;/p&gt;
&lt;h3 id=&quot;comparing-node-ids&quot;&gt;Comparing Node IDs&lt;/h3&gt;
&lt;p&gt;We can check to see if two paths have the same head or are both empty in &lt;em&gt;O(1)&lt;/em&gt;. We'll use &lt;code&gt;(==)&lt;/code&gt; for this under the assumption that we mentioned early on that all identifiers that we use in the paths will be &lt;em&gt;globally unique&lt;/em&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; == &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ s _ == &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ t _ = s == t
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a     == &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; b     = a == b
  &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a _ _ == &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; b _ _ = a == b
  _         == _         = &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are each &lt;em&gt;O(1)&lt;/em&gt; to compute.&lt;/p&gt;
&lt;h3 id=&quot;monotonicity&quot;&gt;Monotonicity&lt;/h3&gt;
&lt;p&gt;We can modify the algorithm for &lt;code&gt;keep&lt;/code&gt; to work with any monotone predicate that transitions from &lt;code&gt;False&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; at most once during the walk up the path to the root.&lt;/p&gt;
&lt;p&gt;As with &lt;code&gt;keep&lt;/code&gt;, the resulting algorithm will take at most &lt;em&gt;O(log h)&lt;/em&gt; applications of the predicate and can run in &lt;em&gt;O(log h)&lt;/em&gt; time if the predicate is &lt;em&gt;O(1)&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;unique-representation&quot;&gt;Unique Representation&lt;/h3&gt;
&lt;p&gt;There are many number systems we could have chosen to use for our paths. One of the nice properties of skew binary that I alluded to earlier is that there is precisely one representation for each natural number in skew binary. Other number systems often give up this property to get other properties.&lt;/p&gt;
&lt;p&gt;Let's use it.&lt;/p&gt;
&lt;p&gt;By knowing that we have a unique representation for a given number in skew binary, we can know that our skew binary random access list has a unique &lt;em&gt;shape&lt;/em&gt; for a given number of entries!&lt;/p&gt;
&lt;p&gt;This means that we can walk the spine of two random access lists of the same length at the same time in lock-step, and we'll visit the same number of trees, of the exact same size.&lt;/p&gt;
&lt;p&gt;So, if we go back to &lt;code&gt;keep&lt;/code&gt;, we can modify the algorithm to work with a pair of paths, computing &lt;code&gt;(==)&lt;/code&gt; which is &lt;em&gt;O(1)&lt;/em&gt;. The fact that our identifiers are globally unique mean that once we find a match, all the parents from then on up the tree should also match.&lt;/p&gt;
&lt;p&gt;We effectively gallop along the spines of our two lists of trees, searching for a match, then back up and search through the two trees we have searching for the first match.&lt;/p&gt;
&lt;p&gt;Monotonicity was required to let us overshoot, and then go back.&lt;/p&gt;
&lt;p&gt;Now we can define &lt;code&gt;lca'&lt;/code&gt;, which requires the two paths to have the same length:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; h@(&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w x xs) (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ y ys)
  | x == y = h
  | xs == ys = lcaT w x y ys
  | otherwise = lca' xs ys
&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; _ _ = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ la ra) (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ lb rb) ts
  | la == lb = consT w2 la (consT w2 ra ts)
  | ra == rb = lcaT w2 la lb (consT w ra ts)
  | otherwise = lcaT w2 ra rb ts
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; _ _ _ ts = ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then a full &lt;code&gt;lca&lt;/code&gt; just trims first:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; xs ys = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare nxs nys &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; lca' xs (keep nxs ys)
  &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; lca' xs ys
  &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; lca' (keep nys xs) ys
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  nxs = size xs
  nys = size ys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/online-lca/#lca-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;all-together-now&quot;&gt;All Together Now&lt;/h2&gt;
&lt;p&gt;To show that I'm not just talking nonsense, let's take all of that and put it in an active haskell snippet that you can play with.&lt;/p&gt;
&lt;p&gt;Click Run to see it in action.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List (&lt;span class=&quot;hljs-title&quot;&gt;unfoldr&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a     == &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; b     = a == b
  &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a _ _ == &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; b _ _ = a == b
  _         == _         = &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
         &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; == &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ s _ == &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ t _ = s == t

&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; n _ _ _) = n

&lt;span class=&quot;hljs-title&quot;&gt;consT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;consT&lt;/span&gt; w t ts = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (w + size ts) w t ts

&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; n w t (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w' t2 ts))
  | w == w' = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (n + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * w + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k t t2) ts
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; k ts = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (size ts + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) ts

&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) ts)     = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (k, ts)
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k l r) ts) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (k, consT w2 l (consT w2 r ts))
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keep&lt;/span&gt; k xs@(&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; n w t ts)
  | k &amp;gt;= n = xs
  | otherwise = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k (n - w) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
     &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; keepT (k - n + w) w t ts
     &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; ts
     &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; keep k ts

&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; n w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ l r) ts = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare n w2 &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; keepT n w2 r ts
  &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; consT w2 r ts
  &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; | n == w - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; -&amp;gt; consT w2 l (consT w2 r ts)
     | otherwise -&amp;gt; keepT (n - w2) w2 l (consT w2 r ts)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keepT&lt;/span&gt; _ _ _ ts = ts

&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; h@(&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ w x xs) (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ _ y ys)
  | x == y = h
  | xs == ys = lcaT w x y ys
  | otherwise = lca' xs ys
&lt;span class=&quot;hljs-title&quot;&gt;lca'&lt;/span&gt; _ _ = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ la ra) (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ lb rb) ts
  | la == lb = consT w2 la (consT w2 ra ts)
  | ra == rb = lcaT w2 la lb (consT w ra ts)
  | otherwise = lcaT w2 ra rb ts
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; w2 = div w &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lcaT&lt;/span&gt; _ _ _ ts = ts

&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lca&lt;/span&gt; xs ys = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare nxs nys &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; lca' xs (keep nxs ys)
  &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; lca' xs ys
  &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; lca' (keep nys xs) ys
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  nxs = size xs
  nys = size ys

&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; = foldr cons &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;toList&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Path&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;]
&lt;span class=&quot;hljs-title&quot;&gt;toList&lt;/span&gt; = unfoldr uncons

&lt;span class=&quot;hljs-title&quot;&gt;xs&lt;/span&gt; = fromList [&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
&lt;span class=&quot;hljs-title&quot;&gt;ys&lt;/span&gt; = fromList [&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ toList (lca xs ys)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;/h2&gt;
&lt;p&gt;With that we can compute an &lt;code&gt;lca&lt;/code&gt; in logarithmic time, without preprocessing.&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;My algorithm requires no preprocessing step&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;O(log h)&lt;/em&gt; LCA query type in h, the length of the path&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;O(1)&lt;/em&gt; to &lt;code&gt;cons&lt;/code&gt; onto the end of the path.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;O(1)&lt;/em&gt; to compare paths for equality.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is no need to store the entire tree locally, merely the paths you are currently using. This helps with distribution and parallelization when working with large trees.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As an on-line algorithm the tree can grow downward from any node without requiring costly recalculations. This renders it suitable for use in version control and other domains where we constantly extend the trees.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I've preserved all of the benefits of the naïve algorithm, while drastically reducing the costs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is a heck of a lot simpler than the off-line algorithms!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This code is packaged up on hackage as the &lt;a href=&quot;https://hackage.haskell.org/package/lca&quot;&gt;&lt;code&gt;lca&lt;/code&gt;&lt;/a&gt; package. There it has a few refinements. In particular in addition to the integer identifiers for each entry, I store some user annotation making the paths &lt;code&gt;Traversable&lt;/code&gt;. Secondly, while trimming the path, it is easy to calculate a monoidal summary of what we trimmed off.&lt;/p&gt;
&lt;p&gt;If we consider monoids that cost &lt;em&gt;O(1)&lt;/em&gt; to do its work, then the cost model doesn't change. This version is in &lt;a href=&quot;https://hackage.haskell.org/packages/archive/lca/0.2.4/doc/html/Data-LCA-Online-Monoidal.html&quot;&gt;Data.LCA.Online.Monoidal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This isn't the end of the story. There are (newer) algorithms that can let us update a more static form of an LCA tree in an imperative setting, permitting us to split a node in the path in O(1) or extend a path downward by one in O(1), just like we can do here. However, these retain the cost that you have to preprocess and store the entire tree rather than just information about your active path, unlike the approach given here.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 14th, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/online-lca/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Unlifted Structures</title><link>https://comonad.com/reader/2015/unlifted-structures/</link><guid isPermaLink="false">https://comonad.com/reader/2015/unlifted-structures/</guid><pubDate>Thu, 27 Aug 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 27 August 2015&lt;/p&gt;&lt;p&gt;An &lt;code&gt;ArrayArray#&lt;/code&gt; is just an &lt;code&gt;Array#&lt;/code&gt; with a modified invariant. It points directly to other unlifted &lt;code&gt;ArrayArray#&lt;/code&gt;'s or &lt;code&gt;ByteArray#&lt;/code&gt;'s.&lt;/p&gt;
&lt;p&gt;While those live in &lt;code&gt;#&lt;/code&gt;, they are garbage collected objects, so this all lives on the heap.&lt;/p&gt;
&lt;p&gt;They were added to make some of the Data Parallel Haskell stuff fast when it has to deal with nested arrays.&lt;/p&gt;
&lt;p&gt;I'm currently abusing them as a placeholder for a better thing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; In the reddit thread for this post &lt;a href=&quot;https://www.reddit.com/r/haskell/comments/3im7ha/edward_kmett_unlifted_structures/cuhski4&quot;&gt;I wound up explaining a bit about what all the fiddly &lt;code&gt;#&lt;/code&gt;'s mean.&lt;/a&gt; If you are having trouble following along, you might want to start there.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Consider the scenario where you naively write a classic doubly-linked list (DLL) in Haskell.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;)) (&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Chasing from one DLL to the next requires following 3 pointers on the heap!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DLL ~&amp;gt; IORef (Maybe DLL) ~&amp;gt; MutVar# RealWorld (Maybe DLL) ~&amp;gt; Maybe DLL ~&amp;gt; DLL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is 3 levels of indirection!&lt;/p&gt;
&lt;p&gt;We can trim one easily by simply unpacking the IORef with &lt;code&gt;-funbox-strict-fields&lt;/code&gt; or &lt;code&gt;UNPACK&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can trim another by adding a &lt;code&gt;Nil&lt;/code&gt; constructor to &lt;code&gt;DLL&lt;/code&gt; and worsening our representation.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) !(&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but now we're still stuck with one level of indirection&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DLL ~&amp;gt; MutVar# RealWorld DLL ~&amp;gt; DLL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that every operation we perform on this structure will be about half of the speed of an implementation in most other languages assuming we're memory bound on loading things into cache!&lt;/p&gt;
&lt;h2 id=&quot;making-progress&quot;&gt;Making Progress&lt;/h2&gt;
&lt;p&gt;I have been working on a number of data structures where the indirection of going from something in &lt;code&gt;*&lt;/code&gt; out to an object in &lt;code&gt;#&lt;/code&gt; which contains the real pointer to my target and coming back effectively doubles my runtime.&lt;/p&gt;
&lt;p&gt;We need to go out to the &lt;code&gt;MutVar#&lt;/code&gt; because we are allowed to put the &lt;code&gt;MutVar#&lt;/code&gt; onto the mutable list when we dirty it. There is a well defined write-barrier there.&lt;/p&gt;
&lt;p&gt;I could change out the representation to use&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MutableArray&lt;/span&gt;# &lt;span class=&quot;hljs-type&quot;&gt;RealWorld&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can just store two pointers in the &lt;code&gt;MutableArray#&lt;/code&gt; every time, but this doesn't help &lt;em&gt;much&lt;/em&gt; directly. It has reduced the amount of distinct addresses in memory from 3 per object to 2.&lt;/p&gt;
&lt;p&gt;I still have to go out to the heap from my &lt;code&gt;DLL&lt;/code&gt; and get to the array object and then chase it to the next &lt;code&gt;DLL&lt;/code&gt; and chase that to the next array. I do get my two pointers together in memory though. I'm paying for a card marking table as well, which I don't particularly need with just two pointers, but we can shed that with the &lt;code&gt;SmallMutableArray#&lt;/code&gt; machinery added back in 7.10, which is just the old array code as a new data type, which can speed things up a bit when you don't have very big arrays:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;SmallMutableArray&lt;/span&gt;# &lt;span class=&quot;hljs-type&quot;&gt;RealWorld&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if I wanted my object itself to live in # and have two mutable fields and be able to share the same write barrier?&lt;/p&gt;
&lt;p&gt;An &lt;code&gt;ArrayArray#&lt;/code&gt; points directly to other unlifted array types. What if we have one &lt;code&gt;# -&amp;gt; *&lt;/code&gt; wrapper on the outside to deal with the impedence mismatch between the imperative world and Haskell, and then just let the &lt;code&gt;ArrayArray#&lt;/code&gt;'s hold other &lt;code&gt;ArrayArray#&lt;/code&gt;s?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MutableArrayArray&lt;/span&gt;# &lt;span class=&quot;hljs-type&quot;&gt;RealWorld&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;now I need to make up a new &lt;code&gt;Nil&lt;/code&gt;, which I can just make be a special &lt;code&gt;MutableArrayArray#&lt;/code&gt; I allocate on program startup. I can even abuse pattern synonyms. Alternately I can exploit the internals further to make this cheaper.&lt;/p&gt;
&lt;p&gt;Then I can use the &lt;code&gt;readMutableArrayArray#&lt;/code&gt; and &lt;code&gt;writeMutableArrayArray#&lt;/code&gt; calls to directly access the preceding and next entry in the linked list.&lt;/p&gt;
&lt;p&gt;So now we have one &lt;code&gt;DLL&lt;/code&gt; wrapper which just 'bootstraps me' into a strict world, and everything there lives in &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;next&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;next&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; readMutableArrayArray# s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
   (# s', n #) -&amp;gt; (# s', &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; n #)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out GHC is quite happy to optimize all of that code to keep things unboxed. The &lt;code&gt;DLL&lt;/code&gt; wrappers get removed pretty easily when they are known strict and you chain operations of this sort!&lt;/p&gt;
&lt;p&gt;In each of these calls we leap from box to box like &lt;a href=&quot;https://www.youtube.com/watch?v=jgxL-PwmY7s&quot;&gt;Maru the cat&lt;/a&gt;, and it is the compiler's job to make the boxes all go away.&lt;/p&gt;
&lt;p&gt;With this I've made a strict little universe and shoved it out on the heap.&lt;/p&gt;
&lt;p&gt;But as it stands, we don't have a portal back to the &quot;real world&quot;.&lt;/p&gt;
&lt;h2 id=&quot;unboxed&quot;&gt;Unboxed&lt;/h2&gt;
&lt;p&gt;Now I have one outermost indirection pointing to an array that points directly to other arrays.&lt;/p&gt;
&lt;p&gt;I'm stuck paying for a card marking table per object, but I can fix that by duplicating the code for &lt;code&gt;MutableArrayArray#&lt;/code&gt; and using a &lt;code&gt;SmallMutableArray#&lt;/code&gt;. I can hack up primops that let me store a mixture of &lt;code&gt;SmallMutableArray#&lt;/code&gt; fields and normal ones in the data structure. Operationally, I can just &lt;code&gt;unsafeCoerce#&lt;/code&gt; the existing &lt;code&gt;SmallMutableArray#&lt;/code&gt; primitives to change the kind of one of the arguments it takes!&lt;/p&gt;
&lt;p&gt;This is almost ideal, but not quite. I often have fields that would be best left unboxed.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) !(&lt;span class=&quot;hljs-type&quot;&gt;IORef&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DLL&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;was able to unpack the &lt;code&gt;Int&lt;/code&gt;, but we lost that. We can currently at best point one of the entries of the &lt;code&gt;SmallMutableArray#&lt;/code&gt; at a boxed or add a &lt;code&gt;MutableByteArray#&lt;/code&gt; for all of our misc. data and shove the &lt;code&gt;Int&lt;/code&gt; in question in there.&lt;/p&gt;
&lt;p&gt;If I were to implement a HAMT, like &lt;code&gt;HashMap&lt;/code&gt; this way I need to store masks and administrivia as I walk down the tree. Having to go off to the side costs me almost the entire win from avoiding the first pointer chase!&lt;/p&gt;
&lt;p&gt;The other day I posted about this to the &lt;code&gt;ghc-devs@&lt;/code&gt; mailing list, and Ryan Yates suggested that he may be able to help.&lt;/p&gt;
&lt;p&gt;If we had a heap object we could construct that had n words with unsafe access and m pointers to other heap objects, one that could put itself on the mutable list when any of those pointers changed then I could shed this last factor of two in all circumstances.&lt;/p&gt;
&lt;h2 id=&quot;prototype&quot;&gt;Prototype&lt;/h2&gt;
&lt;p&gt;Over the last few days I've put together a small prototype implementation with a few non-trivial imperative data structures for things like Tarjan's link-cut trees, the list labeling problem and order-maintenance.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ekmett/structs&quot;&gt;https://github.com/ekmett/structs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notable bits:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ekmett/structs/blob/9ff2818f888aff4789b7a41077a674a10d15e6ee/src/Data/Struct/Internal/LinkCut.hs&quot;&gt;Data.Struct.Internal.LinkCut&lt;/a&gt; provides an implementation of link-cut trees in this style.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ekmett/structs/blob/9ff2818f888aff4789b7a41077a674a10d15e6ee/src/Data/Struct/Internal.hs&quot;&gt;Data.Struct.Internal&lt;/a&gt; provides the rather horrifying guts that make it go fast.&lt;/p&gt;
&lt;p&gt;Once compiled with -O or -O2, if you look at the core, almost all the references to the &lt;code&gt;LinkCut&lt;/code&gt; or &lt;code&gt;Object&lt;/code&gt; data constructor get optimized away, and we're left with beautiful strict code directly mutating our underlying representation.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 27th, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/unlifted-structures/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>On the unsafety of interleaved I/O</title><link>https://comonad.com/reader/2015/on-the-unsafety-of-interleaved-io/</link><guid isPermaLink="false">https://comonad.com/reader/2015/on-the-unsafety-of-interleaved-io/</guid><pubDate>Wed, 22 Jul 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 22 July 2015&lt;/p&gt;&lt;p&gt;One area where I'm at odds with the prevailing winds in Haskell is lazy I/O. It's often said that lazy I/O is evil, scary and confusing, and it breaks things like referential transparency. Having a soft spot for it, and not liking most of the alternatives, I end up on the opposite side when the topic comes up, if I choose to pick the fight. I usually don't feel like I come away from such arguments having done much good at giving lazy I/O its justice. So, I thought perhaps it would be good to spell out my whole position, so that I can give the best defense I can give, and people can continue to ignore it, without costing me as much time in the future. :)&lt;/p&gt;
&lt;p&gt;So, what's the argument that lazy I/O, or &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; on which it's based, breaks referential transparency? It usually looks something like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;swap&lt;/span&gt; (x, y) = (y, x)

&lt;span class=&quot;hljs-title&quot;&gt;setup&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  r1 &amp;lt; - newIORef &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  r2 &amp;lt;- newIORef &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  v1 &amp;lt;- unsafeInterleaveIO $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; writeIORef r2 &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; ; readIORef r1
  v2 &amp;lt;- unsafeInterleaveIO $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; writeIORef r1 &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; ; readIORef r2
  return (v1, v2)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  p1 &amp;lt;- setup
  p2 &amp;lt;- setup
  print p1
  print . swap $ p2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I ran this, and got:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;)
(&lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So this is supposed to demonstrate that the pure values depend on evaluation order, and we have broken a desirable property of Haskell.&lt;/p&gt;
&lt;p&gt;First a digression. Personally I distinguish the terms, &quot;referential transparency,&quot; and, &quot;purity,&quot; and use them to identify two desirable properties of Haskell. The first I use for the property that allows you to factor your program by introducing (or eliminating) named subexpressions. So, instead of:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; e e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we are free to write:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;let&lt;/span&gt; x = e &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; f x x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or some variation. I have no argument for this meaning, other than it's what I thought it meant when I first heard the term used with respect to Haskell, it's a useful property, and it's the best name I can think of for the property. I also (of course) think it's better than some of the other explanations you'll find for what people mean when they say Haskell has referential transparency, since it doesn't mention functions or &quot;values&quot;. It's just about equivalence of expressions.&lt;/p&gt;
&lt;p&gt;Anyhow, for me, the above example is in no danger of violating referential transparency. There is no factoring operation that will change the meaning of the program. I can even factor out &lt;code&gt;setup&lt;/code&gt; (or inline it, since it's already named):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; m = setup
  &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; p1 &amp;lt; - m
        p2 &amp;lt;- m
        print p1
        print . swap $ p2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the way in which &lt;code&gt;IO&lt;/code&gt; preserves referential transparency, unlike side effects, in my view (note: the embedded language represented by &lt;code&gt;IO&lt;/code&gt; does not have this property, since otherwise &lt;code&gt;p1&lt;/code&gt; could be used in lieu of &lt;code&gt;p2&lt;/code&gt;; this is why you shouldn't spend much time writing &lt;code&gt;IO&lt;/code&gt; stuff, because it's a bad language embedded in a good one).&lt;/p&gt;
&lt;p&gt;The other property, &quot;purity,&quot; I pull from Amr Sabry's paper, &lt;a href=&quot;http://www.cs.indiana.edu/~sabry/papers/purelyFunctional.ps&quot;&gt;What is a Purely Functional Language?&lt;/a&gt; There he argues that a functional language should be considered &quot;pure&quot; if it is an extension of the lambda calculus in which there are no contexts which observe differences in evaluation order. Effectively, evaluation order must only determine whether or not you get an answer, not change the answer you get.&lt;/p&gt;
&lt;p&gt;This is slightly different from my definition of referential transparency earlier, but it's also a useful property to have. Referential transparency tells us that we can freely refactor, and purity tells us that we can change the order things are evaluated, both without changing the meaning of our programs.&lt;/p&gt;
&lt;p&gt;Now, it would seem that the original interleaving example violates purity. Depending on the order that the values are evaluated, opponents of lazy I/O say, the values change. However, this argument doesn't impress me, because I think the proper way to think about &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; is as concurrency, and in that case, it isn't very strange that the results of running it would be non-deterministic. And in that case, there's not much you can do to prove that the evaluation order is affecting results, and that you aren't simply very unlucky and always observing results that happen to correspond to evaluation order.&lt;/p&gt;
&lt;p&gt;In fact, there's something I didn't tell you. I didn't use the &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; from base. I wrote my own. It looks like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveIO&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveIO&lt;/span&gt; action = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  iv &amp;lt; - new
  forkIO $
    randomRIO (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;) &amp;gt;&amp;gt;= threadDelay . (*&lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;) &amp;gt;&amp;gt;
    action &amp;gt;&amp;gt;= write iv
  return . read $ iv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;iv&lt;/code&gt; is an &lt;code&gt;IVar&lt;/code&gt; (I used &lt;a href=&quot;https://hackage.haskell.org/package/ivar-simple&quot;&gt;ivar-simple&lt;/a&gt;). The pertinent operations on them are:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;new&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IVar&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;write&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IVar&lt;/span&gt; a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;read&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IVar&lt;/span&gt; a -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;new&lt;/code&gt; creates an empty &lt;code&gt;IVar&lt;/code&gt;, and we can &lt;code&gt;write&lt;/code&gt; to one only once; trying to write a second time will throw an exception. But this is no problem for me, because I obviously only attempt to write once. &lt;code&gt;read&lt;/code&gt; will block until its argument is actually is set, and since that can only happen once, it is considered safe for &lt;code&gt;read&lt;/code&gt; to not require &lt;code&gt;IO&lt;/code&gt;. [1]&lt;/p&gt;
&lt;p&gt;Using this and &lt;code&gt;forkIO&lt;/code&gt;, one can easily write something like &lt;code&gt;unsafeInterleaveIO&lt;/code&gt;, which accepts an &lt;code&gt;IO a&lt;/code&gt; argument and yields an &lt;code&gt;IO a&lt;/code&gt; whose result is guaranteed to be the result of running the argument at some time in the future. The only difference is that the real &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; schedules things just in time, whereas mine schedules them in a relatively random order (I'll admit I had to try a few times before I got the 'expected' lazy IO answer).&lt;/p&gt;
&lt;p&gt;But, we could even take this to be the specification of interleaving. It runs &lt;code&gt;IO&lt;/code&gt; actions concurrently, and you will be fine as long as you aren't attempting to depend on the exact scheduling order (or whether things get scheduled at all in some cases).&lt;/p&gt;
&lt;p&gt;In fact, thinking of lazy I/O as concurrency turns most spooky examples into threading problems that I would expect most people to consider rather basic. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don't pass a handle to another thread and close it in the original.&lt;/li&gt;
&lt;li&gt;Don't fork more file-reading threads than you have file descriptors.&lt;/li&gt;
&lt;li&gt;Don't fork threads to handle files if you're concerned about the files being closed deterministically.&lt;/li&gt;
&lt;li&gt;Don't read from the same handle in multiple threads (unless you don't care about each thread seeing a random subsequence of the stream).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And of course, the original example in this article is just non-determinism introduced by concurrency, but not of a sort that requires fundamentally different explanation than fork. The main pitfall, in my biased opinion, is that the scheduling for interleaving is explained in a way that encourages people to try to guess exactly what it will do. But the presumption of purity (and the reordering GHC actually does based on it) actually means that you cannot assume that much more about the scheduling than you can about my scheduler, at least in general.&lt;/p&gt;
&lt;p&gt;This isn't to suggest that lazy I/O is appropriate for every situation. Sometimes the above advice means that it is not appropriate to use concurrency. However, in my opinion, people are over eager to ban lazy I/O even for simple uses where it is the nicest solution, and justify it based on the 'evil' and 'confusing' ascriptions. But, personally, I don't think this is justified, unless one does the same for pretty much all concurrency.&lt;/p&gt;
&lt;p&gt;I suppose the only (leading) question left to ask is which should be declared unsafe, fork or ivars, since together they allow you to construct a(n even less deterministic) &lt;code&gt;unsafeInterleaveIO&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;[1] Note that there are other implementations of &lt;code&gt;IVar&lt;/code&gt;. I'd expect the most popular to be in &lt;a href=&quot;https://hackage.haskell.org/package/monad-par&quot;&gt;monad-par&lt;/a&gt; by Simon Marlow. That allows one to construct an operation like &lt;code&gt;read&lt;/code&gt;, but it is actually &lt;em&gt;less&lt;/em&gt; deterministic in my construction, because it seems that it will not block unless perhaps you write and read within a single 'transaction,' so to speak.&lt;/p&gt;
&lt;p&gt;In fact, this actually breaks referential transparency in conjunction with &lt;code&gt;forkIO&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;deref&lt;/span&gt; = runPar . get

&lt;span class=&quot;hljs-title&quot;&gt;randomDelay&lt;/span&gt; = randomRIO (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) &amp;gt;&amp;gt;= threadDelay . (&lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;*)

&lt;span class=&quot;hljs-title&quot;&gt;myHandle&lt;/span&gt; m = m `catch` \(_ :: &lt;span class=&quot;hljs-type&quot;&gt;SomeExpression&lt;/span&gt;) -&amp;gt; putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;Bombed&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;mySpawn&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IVar&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;mySpawn&lt;/span&gt; action = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  iv &amp;lt; - runParIO new
  forkIO $ randomDelay &amp;gt;&amp;gt; action &amp;gt;&amp;gt;= runParIO . put_ iv
  return iv

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  iv &amp;lt; - mySpawn (return &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;)
  myHandle . print $ deref iv
  randomDelay
  myHandle . print $ deref iv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes this will print &quot;Bombed&quot; twice, and sometimes it will print &quot;Bombed&quot; followed by &quot;True&quot;. The latter will never happen if we factor out the &lt;code&gt;deref iv&lt;/code&gt; however. The blocking behavior is essential to &lt;code&gt;deref&lt;/code&gt; maintaining referential transparency, and it seems like monad-par only blocks within a single &lt;code&gt;runPar&lt;/code&gt;, not across multiples. Using ivar-simple in this example always results in &quot;True&quot; being printed twice.&lt;/p&gt;
&lt;p&gt;It is also actually possible for &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; to break referential transparency if it is implemented incorrectly (or if the optimizer mucks with the internals in some bad way). But I haven't seen an example that couldn't be considered a bug in the implementation rather than some fundamental misbehavior. And my reference implementation here (with a suboptimal scheduler) suggests that there is no break that isn't just a bug.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/on-the-unsafety-of-interleaved-io/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Discrimination is Wrong: Improving Productivity</title><link>https://comonad.com/reader/talks/discrimination-zurihac-2015/</link><guid isPermaLink="false">https://comonad.com/reader/talks/discrimination-zurihac-2015/</guid><pubDate>Sat, 30 May 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 30 May 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;cB8DapKQz-I&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cB8DapKQz-I&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p class=&quot;editorial&quot;&gt;Presented at ZuriHac 2015; recording published by Google TechTalks.&lt;/p&gt;&lt;p&gt;Discrimination is Wrong: Improving Productivity — ZuriHac 2015.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://raw.githubusercontent.com/zfoh/HaskellerZ/master/meetups/20150530-ZuriHac2015_Edward_Kmett-Discrimination_is_Wrong_Improving_Productivity/Discrimination%20-%20Zurihac.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cB8DapKQz-I&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/discrimination-zurihac-2015/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Moore for Less</title><link>https://comonad.com/reader/2015/moore-for-less/</link><guid isPermaLink="false">https://comonad.com/reader/2015/moore-for-less/</guid><pubDate>Thu, 28 May 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 28 May 2015&lt;/p&gt;&lt;p&gt;I was playing around while stuck on a plane this morning, and realized a few things that had previously escaped me about &lt;a href=&quot;http://en.wikipedia.org/wiki/Moore_machine&quot;&gt;Moore machines&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In previous posts, I've talked about the notion of an (infinite) Moore machine.&lt;/p&gt;
&lt;p&gt;Here we have a machine where each state &lt;code&gt;Moore a b&lt;/code&gt; has a label &lt;code&gt;b&lt;/code&gt;, and given an input &lt;code&gt;a&lt;/code&gt; we transition along an edge to a new state. Unlike a traditional Moore machine, we may well have an infinite number of states, which removes all those pesky limitations on what you can recognize with such a machine.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this form it can be seen to be an &lt;code&gt;Cofree&lt;/code&gt; comonad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that &lt;code&gt;Moore a b&lt;/code&gt; is isomorphic to &lt;code&gt;Cofree ((-&amp;gt;) a) b&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;soul-of-a-nu-machine&quot;&gt;Soul of a Nu Machine&lt;/h2&gt;
&lt;p&gt;An equivalent definition of a Moore machine that &lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/&quot;&gt;I've covered before&lt;/a&gt; is to switch to an explicit 'state' type.&lt;/p&gt;
&lt;p&gt;We can derive that definition from the more direct definition above by one of several different means.&lt;/p&gt;
&lt;p&gt;Probably the most straightforward way to do so is to exploit the fact that &lt;code&gt;Cofree f a = Fix (Compose ((,) a) f)&lt;/code&gt;, where &lt;code&gt;Fix f&lt;/code&gt; is the greatest fixed point of &lt;code&gt;f&lt;/code&gt;, and look at the two different ways to encode the greatest fixed point in Haskell.&lt;/p&gt;
&lt;p&gt;The usual definition of &lt;code&gt;Fix&lt;/code&gt; is given by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fix&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;out&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This definition exploits the fact that the least and greatest fixed points are the same, but we can also just use the direct definition as the greatest fixed point, which we get when we write down the definition of an anamorphism, which we can use to build a member of the greatest fixed point of &lt;code&gt;f&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and just take its type signature as the definition of &lt;code&gt;Nu&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; :: (s -&amp;gt; f s) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f

&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Nu&lt;/code&gt; represents the greatest fixed point in a much more portable way than &lt;code&gt;Fix&lt;/code&gt;. &lt;code&gt;Fix&lt;/code&gt; only really works as a greatest fixed point due to laziness in Haskell. In a strict language these two defintions are not equivalent.&lt;/p&gt;
&lt;p&gt;Substituting &lt;code&gt;Nu&lt;/code&gt; into &lt;code&gt;Cofree&lt;/code&gt; instead of &lt;code&gt;Fix&lt;/code&gt; we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Cofree f b =
Nu (Compose ((,) b) f) =
∃s. (s -&amp;gt; Compose ((,) b) f s, s) =
∃s. (s -&amp;gt; (b, f s), s) =
∃s. (s -&amp;gt; b, s -&amp;gt; f s, s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the particular case of a Moore machine:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Moore a b =
Cofree ((-&amp;gt;) a) b =
∃s. (s -&amp;gt; b, s -&amp;gt; a -&amp;gt; s, s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This corresponds to the data type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: (s -&amp;gt; b) -&amp;gt; (s -&amp;gt; a -&amp;gt; s) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've talked about this data type before, as has &lt;a href=&quot;http://www.haskellforall.com/2013/08/composable-streaming-folds.html&quot;&gt;Gabriel Gonzalez&lt;/a&gt;. I have it packaged up in &lt;a href=&quot;https://hackage.haskell.org/package/folds&quot;&gt;my &lt;code&gt;folds&lt;/code&gt; package&lt;/a&gt;, and he has a version of it in &lt;a href=&quot;https://hackage.haskell.org/package/foldl&quot;&gt;his &lt;code&gt;foldl&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;distributive-functors-represent&quot;&gt;Distributive Functors, Represent!&lt;/h2&gt;
&lt;p&gt;Now for something new: In category theory a representable functor &lt;code&gt;f&lt;/code&gt; is a functor for which there exists an object &lt;code&gt;x&lt;/code&gt; such that we can equip our functor with a natural isomorphism between &lt;code&gt;f a&lt;/code&gt; and &lt;code&gt;(x -&amp;gt; a)&lt;/code&gt;. It describes all of the arrows out of some object &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I have long had this definition split across two packages.&lt;/p&gt;
&lt;p&gt;We first have the &quot;haskell 98&quot; &lt;code&gt;distributive&lt;/code&gt; package, which provides&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Distributive&lt;/span&gt; g &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  distribute :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f (g a) -&amp;gt; g (f a)
  collect :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; g b) -&amp;gt; f a -&amp;gt; g (f b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Distributive&lt;/code&gt; is effectively a co-&lt;code&gt;Traversable&lt;/code&gt;. Given that the package is Haskell 98 / 2010, it can't supply us &lt;code&gt;x&lt;/code&gt;. For every &lt;code&gt;Distributive&lt;/code&gt; functor such an &lt;code&gt;x&lt;/code&gt; should exist though. In the &lt;code&gt;adjunctions&lt;/code&gt; package, you can get your hands on it with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Distributive&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f&lt;/span&gt;
  tabulate :: (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f -&amp;gt; a) -&amp;gt; f a
  index :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;x = Rep f&lt;/code&gt;, and &lt;code&gt;tabulate&lt;/code&gt; and &lt;code&gt;index&lt;/code&gt; are inverses.&lt;/p&gt;
&lt;h2 id=&quot;cofree-anyone&quot;&gt;Cofree Anyone?&lt;/h2&gt;
&lt;p&gt;There is an obvious representation for &lt;code&gt;((-&amp;gt;) x)&lt;/code&gt;, as &lt;code&gt;(x -&amp;gt; a)&lt;/code&gt; is clearly isomorphic to &lt;code&gt;(x -&amp;gt; a)&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; ((-&amp;gt;) x) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; ((-&amp;gt;) x) = x&lt;/span&gt;
  tabulate = id
  index = id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this we can just randomly embellish the definition of a cofree comonad by explicitly choosing &lt;code&gt;s&lt;/code&gt; to be the representation of &lt;em&gt;some&lt;/em&gt; representable functor, and just not telling me what it is.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; k =&amp;gt; k a -&amp;gt; k (f (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; (fmap f k) u s
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; k _ s) = index k s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; (tabulate (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; k u)) u s
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;representable-machines&quot;&gt;Representable Machines&lt;/h2&gt;
&lt;p&gt;Now we're equipped to play with a similarly modified definition of a Moore machine.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; k =&amp;gt; k b -&amp;gt; k (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Above and beyond what we can say about &lt;code&gt;Cofree&lt;/code&gt; in general, we know something else in the &lt;code&gt;Moore&lt;/code&gt; case, namely that both our unknown representable functor &lt;code&gt;k&lt;/code&gt; and &lt;code&gt;(-&amp;gt;) a&lt;/code&gt; are &lt;code&gt;Distributive&lt;/code&gt;, so we can freely interchange them in the definition above. This yields the following definition, in terms of which all subsequent instances are defined:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; k =&amp;gt; k b -&amp;gt; (a -&amp;gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the &lt;code&gt;u&lt;/code&gt; argument isn't used at all in the definition of the &lt;code&gt;Comonad&lt;/code&gt; for &lt;code&gt;Cofree f&lt;/code&gt; and is just silently passed along, these instances for &lt;code&gt;Moore a&lt;/code&gt; work either way.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u b) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (fmap f k) u b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k _ s)   = index k s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (tabulate (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u)) u s
  extend f (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s)  = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (tabulate (f . &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u)) u s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Due to the &lt;code&gt;Representable ((-&amp;gt;) x)&lt;/code&gt; instance no power is lost, but now some choices of &lt;code&gt;k&lt;/code&gt; might be suitable for memoization, acting as a trie to hold onto the results rather than recomputing them each time they are asked.&lt;/p&gt;
&lt;h2 id=&quot;doing-two-things-at-once&quot;&gt;Doing Two Things at Once&lt;/h2&gt;
&lt;p&gt;While I've put the &lt;code&gt;Comonad&lt;/code&gt; for &lt;code&gt;Moore&lt;/code&gt; to good use in previous posts, much of the original motivation for using &lt;code&gt;Moore&lt;/code&gt; was to give us the ability to describe how to fuse together multiple passes over the data.&lt;/p&gt;
&lt;p&gt;To derive the &lt;code&gt;Applicative&lt;/code&gt; for our new machine we'll need suitable functors to use to memoize all of our states. Rather than using functions, let's look for some things that are better behaved.&lt;/p&gt;
&lt;p&gt;The next simpler instance after the naïve function instance above is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; = ()&lt;/span&gt;
  tabulate f = &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (f ())
  index (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a) () = a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, given two representable functors, their composition is also representable:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) = (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;)&lt;/span&gt;
  index (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; fg) (i,j) = index (index fg i) j
  tabulate = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . tabulate . fmap tabulate . curry
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So let's put these instances to work:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a) (\_ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; ()) ()
  &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; kf uf sf &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; ka ua sa =
    &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; ((&amp;lt;$&amp;gt; ka) &amp;lt;$&amp;gt; kf))
          (\x -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; $ (\y -&amp;gt; (,) y &amp;lt;$&amp;gt; ua x) &amp;lt;$&amp;gt; uf x)
          (sf, sa)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt;@&amp;gt;) = (&amp;lt;*&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just the definition we used to use for the &lt;code&gt;foldl&lt;/code&gt;-style &lt;code&gt;Moore&lt;/code&gt; machine, but now instead of using functions from our state, we just use representable functors that have our states as their representations.&lt;/p&gt;
&lt;p&gt;Finally, as a small but useful aside, a &lt;code&gt;Moore&lt;/code&gt; machine is a &lt;code&gt;Profunctor&lt;/code&gt;, so we can map contravariantly over the inputs as well as covariantly over the results.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (g &amp;lt;$&amp;gt; k) (u . f) s
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;stepping-lightly&quot;&gt;Stepping Lightly&lt;/h2&gt;
&lt;p&gt;So how do we run the machine?&lt;/p&gt;
&lt;p&gt;We can feed our machine in one of two ways. We can define&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step1&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;step1&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) = index k (index (u a) s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and rely on the ability to &lt;code&gt;extend (step a)&lt;/code&gt; to change out all of the labels on our machine. This unfortunately builds up and tears down a whole representable functor worth of data.&lt;/p&gt;
&lt;p&gt;On the other hand, we can simply move the start state and get a whole new machine:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u (index (u a) s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The choice between &lt;code&gt;step a&lt;/code&gt; and &lt;code&gt;extend (step1 a)&lt;/code&gt; is indistinguishable to the outside observer except in terms of performance. While &lt;code&gt;step&lt;/code&gt; isn't a Cokleisli arrow, it is much faster.&lt;/p&gt;
&lt;h2 id=&quot;running-a-tab&quot;&gt;Running a Tab&lt;/h2&gt;
&lt;p&gt;That said, we don't have to run the machine one step at a time!&lt;/p&gt;
&lt;p&gt;Dan Piponi once wrote an article on recognizing a regular language with a monoid. What he did was build a data type to represent the tabulation of transitions in his DFA.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;a -&amp;gt; f (Rep f)&lt;/code&gt; in the body of our Moore machine suggests what such a tabulation might look like, generically. It takes &lt;code&gt;a&lt;/code&gt; to a structure that contains references to all the new states.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getTab&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; $ tabulate id
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; fs) (&lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; gs) = &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; (index gs &amp;lt;$&amp;gt; fs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can view this as a form of &lt;code&gt;Endo (Rep f)&lt;/code&gt; that happens to be able to memoize the results of each argument to the function if &lt;code&gt;f&lt;/code&gt; is sufficiently &quot;nice&quot;.&lt;/p&gt;
&lt;p&gt;We can now feed our machine a whole &lt;code&gt;Foldable&lt;/code&gt; container at a time.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;feed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;feed&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u (index (getTab $ foldMap (&lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; . u) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) s)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;compressive-parsing&quot;&gt;Compressive Parsing&lt;/h2&gt;
&lt;p&gt;The next trick is finding the right container type to fold over to make use of the memoized internal states.&lt;/p&gt;
&lt;p&gt;For this, I'll turn to an old package of mine, &lt;code&gt;compressed&lt;/code&gt;, which supplies a rather peculiar &lt;code&gt;LZ78&lt;/code&gt; container type. LZ78 is a compression scheme by Lempel and Ziv that has a number of nice properties for my purposes.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The idea is this:&lt;/p&gt;
&lt;p&gt;1.) You start with a dictionary that maps integers to a list of values and which contains a single entry that maps 0 to the empty string.&lt;/p&gt;
&lt;p&gt;2.) Now you receive (or generate) a series of &lt;code&gt;(Int, value)&lt;/code&gt; pairs, where each &lt;code&gt;Int&lt;/code&gt; represents an existing slot in the dictionary, and the value represents something you want to &lt;code&gt;snoc&lt;/code&gt; onto the end of it to make a fresh dictionary entry.&lt;/p&gt;
&lt;p&gt;More advanced versions of this scheme collect old entries, but we can define a particularly naive LZ78 encoder / decoder very easily.&lt;/p&gt;
&lt;p&gt;We can encode using a variety of different constraint types and times depending on how we represent the dictionary during construction.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;O(n&lt;sup&gt;2&lt;/sup&gt;)&lt;/em&gt; we can construct an LZ78 stream using a list internally, but no more than an &lt;code&gt;Eq&lt;/code&gt; constraint on &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;encodeEq&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; [a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;encodeEq&lt;/span&gt; = go [] &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go _ _ _ [] = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go _ _ p [c] = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c) &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go d f p (c:cs) = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; t = &lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt;.lookup t d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; p' -&amp;gt; go d f p' cs
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; t (go ((t, f):d) (succ f) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; cs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With a &lt;code&gt;Map&lt;/code&gt; our time upgrades to &lt;em&gt;O(n log n)&lt;/em&gt; with an &lt;code&gt;Ord&lt;/code&gt; constraint.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;encodeOrd&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a =&amp;gt; [a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;encodeOrd&lt;/span&gt; = go &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt;.empty &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go _ _ _ [] = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go _ _ p [c] = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c) &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go d f p (c:cs) = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; t = &lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt;.lookup t d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; p' -&amp;gt; go d f p' cs
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; t (go (&lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt;.insert t f d) (succ f) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; cs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also turn to a &lt;code&gt;HashMap&lt;/code&gt; if we have &lt;code&gt;Hashable&lt;/code&gt; inputs.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;encode&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Hashable&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a) =&amp;gt; [a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;encode&lt;/span&gt; = go &lt;span class=&quot;hljs-type&quot;&gt;HashMap&lt;/span&gt;.empty &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go _ _ _ [] = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go _ _ p [c] = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c) &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  go d f p (c:cs) = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; t = &lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; p c &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HashMap&lt;/span&gt;.lookup t d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; p' -&amp;gt; go d f p' cs
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; t (go (&lt;span class=&quot;hljs-type&quot;&gt;HashMap&lt;/span&gt;.insert t f d) (succ f) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; cs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But regardless of how it was constructed, we can &lt;code&gt;decode&lt;/code&gt; with &lt;code&gt;Foldable&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LZ78&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f = go (&lt;span class=&quot;hljs-type&quot;&gt;Seq&lt;/span&gt;.singleton mempty) mempty &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go _ m &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = m
    go s m (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Token&lt;/span&gt; w c) ws) = m `mappend` go (s |&amp;gt; v) v ws &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      v = &lt;span class=&quot;hljs-type&quot;&gt;Seq&lt;/span&gt;.index s w `mappend` f c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key here is that the decompression scheme never actually &lt;em&gt;looks&lt;/em&gt; at the values it decodes, so it is possible to decompress directly in any target &lt;code&gt;Monoid&lt;/code&gt; you want.&lt;/p&gt;
&lt;p&gt;When you do so you'll gain some sharing of intermediate values.&lt;/p&gt;
&lt;p&gt;Other compression schemes may also be useful depending on your application.&lt;/p&gt;
&lt;h2 id=&quot;the-story-so-far&quot;&gt;The Story So Far&lt;/h2&gt;
&lt;p&gt;We can open up such a machine and borrow its internal type of tabulations to generate anything that can be generated by such a machine in parallel or incrementally.&lt;/p&gt;
&lt;p&gt;It is possible to run a &lt;code&gt;Representable&lt;/code&gt; &lt;code&gt;Moore&lt;/code&gt; machine directly on compressed inputs and pay proportionally to the size of the compressed data, not the decompressed data.&lt;/p&gt;
&lt;h2 id=&quot;representability-and-adjunctions&quot;&gt;Representability and Adjunctions&lt;/h2&gt;
&lt;p&gt;In category theory we have the notion of an adjunction.&lt;/p&gt;
&lt;p&gt;Given two functors &lt;code&gt;F : D -&amp;gt; C&lt;/code&gt;, and &lt;code&gt;G : C -&amp;gt; D&lt;/code&gt;, when &lt;code&gt;F a -&amp;gt; b&lt;/code&gt; is naturally isomorphic to &lt;code&gt;a -&amp;gt; G b&lt;/code&gt; we describe this situation in one of several equivalent ways, we say that &lt;code&gt;F -| G&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt; is right adjoint to &lt;code&gt;F&lt;/code&gt;, or &lt;code&gt;F is left adjoint to G&lt;/code&gt;, and if the categories matter, sometimes we'll write &lt;code&gt;F -| G :: C -&amp;gt; D&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Different authors have slightly different conventions on the latter and may give the signature for F instead of G.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The left (or right) adjoint of a functor is unique up to isomorphism if it exists at all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;All adjunctions &lt;code&gt;F -| G :: C -&amp;gt; Hask&lt;/code&gt; have the property that &lt;code&gt;G&lt;/code&gt; is representable and &lt;a href=&quot;http://en.wikipedia.org/wiki/Representable_functor#Left_adjoint&quot;&gt;&lt;code&gt;F ()&lt;/code&gt; represents &lt;code&gt;G&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Since adjoints are unique the fact that the right adjoint is isomorphic to &lt;code&gt;(F () -&amp;gt; a)&lt;/code&gt; lets us go back across the &lt;code&gt;(,) (F ()) -| (-&amp;gt;) (F ())&lt;/code&gt; adjunction and use the uniqueness of adjoints to see &lt;code&gt;F a&lt;/code&gt; is isomorphic to &lt;code&gt;(,) (F ()) a&lt;/code&gt;. In other words, &lt;code&gt;F&lt;/code&gt; contains exactly one &lt;code&gt;a&lt;/code&gt;. On top of that, every left adjoint &lt;code&gt;F :: Hask -&amp;gt; Hask&lt;/code&gt; looks like &lt;code&gt;F = (,) x&lt;/code&gt; for some &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Representable_functor#Uniqueness&quot;&gt;Representations of representable functors are unique up to isomorphism.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all of these constraints, if we write down a class describing adjunctions from &lt;code&gt;Hask -&amp;gt; Hask&lt;/code&gt; it is rather poorly inhabited! All instances of this class are isomorphic (for some &lt;code&gt;s&lt;/code&gt;) to the canonical &lt;code&gt;(,) s -| (-&amp;gt;) s&lt;/code&gt; adjunction that gives rise to the &lt;code&gt;State&lt;/code&gt; monad and &lt;code&gt;Store&lt;/code&gt; comonad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; f -| g &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  leftAdjunct :: (f a -&amp;gt; b) -&amp;gt; a -&amp;gt; g b
  rightAdjunct :: (a -&amp;gt; g b) -&amp;gt; f a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First consider that if &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; are &lt;code&gt;Representable&lt;/code&gt; then &lt;code&gt;Product f g&lt;/code&gt; is isomorphic to &lt;code&gt;(-&amp;gt;) (Either (Rep f) (Rep g))&lt;/code&gt; and we can also look at a couple of our recently explored instances:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Identity&lt;/code&gt; is isomorphic to &lt;code&gt;(-&amp;gt;) ()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; are &lt;code&gt;Representable&lt;/code&gt; then &lt;code&gt;Compose f g&lt;/code&gt; is isomorphic to &lt;code&gt;(-&amp;gt;) (Rep f, Rep g)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you squint at these a bit the representation looks a lot like the &quot;logarithm&quot; of the data type in question. Exponents become products, products become sums, etc. Conor McBride is fond of calling representable functors &quot;Napierian&quot; and using &lt;code&gt;Log&lt;/code&gt; instead of &lt;code&gt;Rep&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since every adjunction gives us a representable functor (the right adjoint), and every representable functor is the right adjoint in some adjunction, and all of this stuff is the same up to isomorphism, we could rephrase everything we just wrote in terms of an adjunction from &lt;code&gt;Hask -&amp;gt; Hask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We get a couple of options (all of equivalent expressive power) for how to arrange things:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: (f -| g) =&amp;gt; g b -&amp;gt; f (a -&amp;gt; g (f ())) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: (f -| g) =&amp;gt; g b -&amp;gt; f (g (a -&amp;gt; f ())) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; :: (f -| g) =&amp;gt; f (g b) -&amp;gt; (a -&amp;gt; g (f ())) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think the last one of those is the most interesting. When &lt;code&gt;f -| g&lt;/code&gt;, then &lt;code&gt;f·g&lt;/code&gt; is a comonad and &lt;code&gt;g·f&lt;/code&gt; is a monad. Here our Moore machine is pairing up some comonad with a function that gives a monadic action that is intimately related to that comonad.&lt;/p&gt;
&lt;p&gt;Since all adjunctions from &lt;code&gt;Hask -&amp;gt; Hask&lt;/code&gt; look like the representable cases we've already explored we haven't yet gained anything from this, but we could work with adjunctions that visit other categories than &lt;code&gt;Hask&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;i-m-my-own-grandpa&quot;&gt;I'm My Own Grandpa&lt;/h2&gt;
&lt;p&gt;There is a nice adjunction from &lt;code&gt;Hask -&amp;gt; Hask&lt;/code&gt;&lt;sup&gt;op&lt;/sup&gt; that we use in Haskell a great deal.&lt;/p&gt;
&lt;p&gt;Using backwards arrows to denote arrows in &lt;code&gt;Hask&lt;/code&gt;&lt;sup&gt;op&lt;/sup&gt;, any such adjunction would look like a statement that &lt;code&gt;f a &amp;lt;- b&lt;/code&gt; is isomorphic to &lt;code&gt;a -&amp;gt; g b&lt;/code&gt;. &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; here are contravariant functors, and if we turn this around we get that &lt;code&gt;b -&amp;gt; f a&lt;/code&gt; is isomorphic to &lt;code&gt;a -&amp;gt; g b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is such an adjunction:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(-&amp;gt; r) -| (-&amp;gt; r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When composed in one direction we get a monad in &lt;code&gt;Hask&lt;/code&gt;, when composed the other way around we get a comonad in &lt;code&gt;Hask&lt;/code&gt;&lt;sup&gt;op&lt;/sup&gt;. This is why &lt;code&gt;Cont r&lt;/code&gt; has no comonadic equivalent. It is its own inverse.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(b -&amp;gt; a -&amp;gt; r)&lt;/code&gt; be isomorphic to &lt;code&gt;(a -&amp;gt; b -&amp;gt; r)&lt;/code&gt;, and this is witnessed by &lt;code&gt;flip&lt;/code&gt; in both directions.&lt;/p&gt;
&lt;h2 id=&quot;less-like-moore&quot;&gt;Less Like Moore&lt;/h2&gt;
&lt;p&gt;Now, we can mechanically massage that last definition of a Moore machine to go round trip through &lt;code&gt;Hask&lt;/code&gt;&lt;sup&gt;op&lt;/sup&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Wat&lt;/span&gt; :: (b -&amp;gt; r -&amp;gt; r) -&amp;gt; a -&amp;gt; (() -&amp;gt; r) -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;() -&amp;gt;&lt;/code&gt; in there adds no value, so we can apply it to &lt;code&gt;()&lt;/code&gt; to get more or less Rich Hickey's notion of a &lt;a href=&quot;http://clojure.org/transducers&quot;&gt;transducer&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Transducer&lt;/span&gt; a b = forall r. (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hickeys's transducers derive from the type signature of &lt;code&gt;foldl&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; :t foldl
&lt;span class=&quot;hljs-title&quot;&gt;foldl&lt;/span&gt; :: (b -&amp;gt; a -&amp;gt; b) -&amp;gt; b -&amp;gt; [a] -&amp;gt; b
&amp;gt;&amp;gt;&amp;gt; :t foldl.foldl
&lt;span class=&quot;hljs-title&quot;&gt;foldl&lt;/span&gt;.foldl :: (b -&amp;gt; a -&amp;gt; b) -&amp;gt; b -&amp;gt; [[a]] -&amp;gt; b
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and you can convert from that form to this form with a couple of judiciously placed &lt;code&gt;flip&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;So in this sense a &lt;code&gt;Transducer&lt;/code&gt; is a &quot;generalized Moore machine&quot;. The generalization here is powerful enough to allow the transducer to emit multiple &lt;code&gt;b&lt;/code&gt;s per &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;representing-transducers&quot;&gt;Representing Transducers&lt;/h2&gt;
&lt;p&gt;But now we have functions to and from some arbitrary &lt;code&gt;r&lt;/code&gt; in our &lt;code&gt;Transducer&lt;/code&gt; definition and we can replay this same motivating trick we used to exploit representations on that definition as well.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Transducer&lt;/span&gt; a b = forall f. &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) -&amp;gt; a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is equivalent to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Transducer&lt;/span&gt; a b = forall f. &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tab&lt;/span&gt; f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact we can apply such a transducer to a Moore machine to get one that turns each &lt;code&gt;a&lt;/code&gt; into potentially several &lt;code&gt;b&lt;/code&gt;s, and makes that whole chain of transitions in the state diagram at once.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;transduce&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Transducer&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a c
&lt;span class=&quot;hljs-title&quot;&gt;transduce&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k u s) t = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; k (getD #. t (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; #. u)) s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, if you work for all tabulations of a function, nothing stops you from working for a monoid through &lt;code&gt;Endo m&lt;/code&gt;, so you might as well just go to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Transducer&lt;/span&gt; a b = forall f. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) -&amp;gt; a -&amp;gt; m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but this is just what &lt;code&gt;lens&lt;/code&gt; calls a &lt;code&gt;Fold&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; a b = forall f. (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) -&amp;gt; a -&amp;gt; f a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are (legally) both &lt;code&gt;Contravariant&lt;/code&gt; and &lt;code&gt;Functor&lt;/code&gt; then your argument must be phantom, and using &lt;code&gt;contramap&lt;/code&gt; and &lt;code&gt;fmap&lt;/code&gt; you can freely change it to anything you want, so this is isomorphic to the last definition.&lt;/p&gt;
&lt;h2 id=&quot;open-thoughts&quot;&gt;Open Thoughts&lt;/h2&gt;
&lt;p&gt;Similar changes can be applied to a &lt;a href=&quot;https://hackage.haskell.org/package/free-4.12.1/docs/Control-Comonad-Trans-Coiter.html&quot;&gt;coiterative comonad generated by a comonad&lt;/a&gt;, which looks very similar to the &lt;code&gt;Mealy&lt;/code&gt; machine even if it has wildly different semantics. But given that coincidence, what does such a &lt;code&gt;Comonad&lt;/code&gt; mean for a &lt;code&gt;Mealy&lt;/code&gt; machine that has a &lt;code&gt;Monoid&lt;/code&gt; on its input type? How would such a machine have to work? What does it do?&lt;/p&gt;
&lt;p&gt;Just like we ultimately massaged the transducer into a form where it was obvious we could make the same machinery work for any &lt;code&gt;Monoid&lt;/code&gt; once it supported tabulated endomorphisms, can do find a series of direct generalizations that take us from a &lt;code&gt;Moore&lt;/code&gt; machine to one that uses an intermediate &lt;code&gt;Monoid&lt;/code&gt;? Either like the &lt;code&gt;M&lt;/code&gt; machine in &lt;code&gt;folds&lt;/code&gt; or using a Monoid action to update the state instead of accepting just any new state.&lt;/p&gt;
&lt;p&gt;We built a tabulation of a deterministic not-necessarily-finite automaton. What about a non-deterministic automaton? For that we can make a set of representations using the trie we get for a representable functor &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getSet&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; $ tabulate (const &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; bs) = &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; $ tabulate $ \i -&amp;gt; index &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; i || index bs i

&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; i = &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; $ tabulate (i==)

&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; i (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; is) = &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; $ tabulate $ \j -&amp;gt; index is j || (i==j)

&lt;span class=&quot;hljs-title&quot;&gt;contains&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rep&lt;/span&gt; f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;contains&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; is) i = index is i
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but it'd probably be better to use a real &quot;Set&quot; in practice for most applications. You need something like &lt;code&gt;Foldable f&lt;/code&gt; as well as &lt;code&gt;Representable&lt;/code&gt; in order to make the &lt;code&gt;Monoid&lt;/code&gt; for&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getN&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This would start to limit the domain to at-most-countably-infinite automata.&lt;/p&gt;
&lt;p&gt;Given that can we define a nice compiler that takes a regular expression builds an NFA state replete with the appropriate functor as it goes, and then converts it to a DFA?&lt;/p&gt;
&lt;p&gt;The compressive parsing technique provided by &lt;code&gt;LZ78&lt;/code&gt; above works for lots of monoids, not just this one.&lt;/p&gt;
&lt;p&gt;For instance, we can modify the code in &lt;a href=&quot;http://www.cse.chalmers.se/~bernardy/PP.pdf&quot;&gt;Efficient Parallel and Incremental Parsing of Practical Context-Free Languages&lt;/a&gt; to work with a &lt;code&gt;Monoid&lt;/code&gt; rather than the notion of a sequence algebra they use there. (A sequence-algebra can be converted to &lt;code&gt;Monoid&lt;/code&gt; by using a finger-tree to peel off one symbol of work on one side.)&lt;/p&gt;
&lt;p&gt;This would let us parse context-free languages using this same machinery.&lt;/p&gt;
&lt;p&gt;The main body of code here is available in this &lt;a href=&quot;https://gist.github.com/ekmett/0b9d00c621d34a352e57&quot;&gt;gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Also, the code above probably needs a couple of tweaks. Notably, it should use a strict pair for the internal state.)&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;
May 28, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/moore-for-less/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Functionally Oblivious (and Succinct)</title><link>https://comonad.com/reader/talks/functionally-oblivious-ifip-2015/</link><guid isPermaLink="false">https://comonad.com/reader/talks/functionally-oblivious-ifip-2015/</guid><pubDate>Tue, 26 May 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 26 May 2015&lt;/p&gt;&lt;p&gt;Slides from the 33rd IFIP Working Group 2.8 meeting, exploring cache-oblivious and succinct data structures.&lt;/p&gt;&lt;p&gt;&lt;a class=&quot;document-download&quot; href=&quot;https://comonad.com/assets/documents/functionally-oblivious-2015.pdf&quot;&gt;Read the slides (PDF · 49 pages)&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/documents/functionally-oblivious-2015.pdf&quot; download=&quot;&quot;&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/functionally-oblivious-ifip-2015/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Categories of Structures in Haskell</title><link>https://comonad.com/reader/2015/categories-of-structures-in-haskell/</link><guid isPermaLink="false">https://comonad.com/reader/2015/categories-of-structures-in-haskell/</guid><pubDate>Mon, 25 May 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 25 May 2015&lt;/p&gt;&lt;p&gt;In the last couple posts I've used some 'free' constructions, and not remarked too much on how they arise. In this post, I'd like to explore them more. This is going to be something of a departure from the previous posts, though, since I'm not going to worry about thinking precisely about bottom/domains. This is more an exercise in applying some category theory to Haskell, &quot;fast and loose&quot;.&lt;/p&gt;
&lt;p&gt;(Advance note: for some continuous code to look at see &lt;a href=&quot;http://code.haskell.org/~dolio/haskell-share/categories-of-structures/COS.hs&quot;&gt;this file&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;First, it'll help to talk about how some categories can work in Haskell. For any kind &lt;code&gt;k&lt;/code&gt; made of &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;(-&amp;gt;)&lt;/code&gt;, [0] we can define a category of type constructors. Objects of the category will be first-class [1] types of that kind, and arrows will be defined by the following type family:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Transformer&lt;/span&gt; f g = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; { ($$) :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; }&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;family&lt;/span&gt; (~&amp;gt;) :: k -&amp;gt; k -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (~&amp;gt;) = (-&amp;gt;)
  (~&amp;gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Transformer&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; a &amp;lt; -&amp;gt; b = (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; a &amp;lt; ~&amp;gt; b = (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, for a base case, * has monomorphic functions as arrows, and categories for higher kinds have polymorphic functions that saturate the constructor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; ~&amp;gt; [] = &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a -&amp;gt; [a]
  &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; ~&amp;gt; (,) = &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a b. &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b -&amp;gt; (a, b)
  &lt;span class=&quot;hljs-type&quot;&gt;StateT&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ReaderT&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s m a. &lt;span class=&quot;hljs-type&quot;&gt;StateT&lt;/span&gt; s m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ReaderT&lt;/span&gt; s m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can of course define identity and composition for these, and it will be handy to do so:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Morph&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; *) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id :: p a a
  (.) :: p b c -&amp;gt; p a b -&amp;gt; p a c
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Morph&lt;/span&gt; (-&amp;gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id x = x
  (g . f) x = g (f x)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Morph&lt;/span&gt; ((~&amp;gt;) :: k -&amp;gt; k -&amp;gt; *)
      =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Morph&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Transformer&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) -&amp;gt; *) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; id
  &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; f . &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; g = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ f . g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These categories can be looked upon as the most basic substrates in Haskell. For instance, every type of kind &lt;code&gt;* -&amp;gt; *&lt;/code&gt; is an object of the relevant category, even if it's a GADT or has other structure that prevents it from being nicely functorial.&lt;/p&gt;
&lt;p&gt;The category for * is of course just the normal category of types and functions we usually call Hask, and it is fairly analogous to the category of sets. One common activity in category theory is to study categories of sets equipped with extra structure, and it turns out we can do this in Haskell, as well. And it even makes some sense to study categories of structures over any of these type categories.&lt;/p&gt;
&lt;p&gt;When we equip our types with structure, we often use type classes, so that's how I'll do things here. Classes have a special status socially in that we expect people to only define instances that adhere to certain equational rules. This will take the place of equations that we are not able to state in the Haskell type system, because it doesn't have dependent types. So using classes will allow us to define more structures that we normally would, if only by convention.&lt;/p&gt;
&lt;p&gt;So, if we have a kind &lt;code&gt;k&lt;/code&gt;, then a corresponding structure will be &lt;code&gt;σ :: k -&amp;gt; Constraint&lt;/code&gt;. We can then define the category &lt;code&gt;(k,σ)&lt;/code&gt; as having objects &lt;code&gt;t :: k&lt;/code&gt; such that there is an instance &lt;code&gt;σ t&lt;/code&gt;. Arrows are then taken to be &lt;code&gt;f :: t ~&amp;gt; u&lt;/code&gt; such that &lt;code&gt;f&lt;/code&gt; &quot;respects&quot; the operations of &lt;code&gt;σ&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a simple example, we have:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  k = *
  σ = &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; :: * -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;

  &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;, [&lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;] :: (*, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt;)

  f :: (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; n) =&amp;gt; m -&amp;gt; n
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; f mempty = mempty
       f (m &amp;lt;&amp;gt; n) = f m &amp;lt;&amp;gt; f n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just the category of monoids in Haskell.&lt;/p&gt;
&lt;p&gt;As a side note, we will sometimes be wanting to quantify over these &quot;categories of structures&quot;. There isn't really a good way to package together a kind and a structure such that they work as a unit, but we can just add a constraint to the quantification. So, to quantify over all &lt;code&gt;Monoid&lt;/code&gt;s, we'll use '&lt;code&gt;forall m. Monoid m =&amp;gt; ...&lt;/code&gt;'.&lt;/p&gt;
&lt;p&gt;Now, once we have these categories of structures, there is an obvious forgetful functor back into the unadorned category. We can then look for free and cofree functors as adjoints to this. More symbolically:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ :: (k,σ) -&amp;gt; k
  &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;   σ :: k -&amp;gt; (k,σ)
  &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ :: k -&amp;gt; (k,σ)

  &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ ⊣ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ ⊣ &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, what would be nicer (for some purposes) than having to look for these is being able to construct them all systematically, without having to think much about the structure &lt;code&gt;σ&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Category theory gives a hint at this, too, in the form of Kan extensions. In category terms they look like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  p : &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;C'&lt;/span&gt;
  f : &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; p f : &lt;span class=&quot;hljs-type&quot;&gt;C'&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; p f : &lt;span class=&quot;hljs-type&quot;&gt;C'&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;

  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; p f c' = end (c : &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt;). &lt;span class=&quot;hljs-type&quot;&gt;Hom_C'&lt;/span&gt;(c', p c) ⇒ f c
  &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; p f c' = coend (c : c). &lt;span class=&quot;hljs-type&quot;&gt;Hom_C'&lt;/span&gt;(p c, c') ⊗ f c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;⇒&lt;/code&gt; is a &quot;power&quot; and &lt;code&gt;⊗&lt;/code&gt; is a copower, which are like being able to take exponentials and products by sets (or whatever the objects of the hom category are), instead of other objects within the category. Ends and coends are like universal and existential quantifiers (as are limits and colimits, but ends and coends involve mixed-variance).&lt;/p&gt;
&lt;p&gt;Some handy theorems relate Kan extensions and adjoint functors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; and &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;

  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; exists and is absolute
  &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt;

  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; exists and is absolute
  &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; ⊣ &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;

  &lt;span class=&quot;hljs-type&quot;&gt;Kan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; is absolute iff &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;. (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Kan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;) ~= &lt;span class=&quot;hljs-type&quot;&gt;Kan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;P&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out we can write down Kan extensions fairly generally in Haskell. Our restricted case is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  p = &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ :: (k,σ) -&amp;gt; k
  f = &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; :: (k,σ) -&amp;gt; (k,σ)

  &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;   σ = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ) &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; :: k -&amp;gt; (k,σ)
  &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ) &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; :: k -&amp;gt; (k,σ)

  g :: (k,σ) -&amp;gt; j
  g . &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;   σ = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ) g
  g . &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; σ) g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As long as the final category is like one of our type constructor categories, ends are universal quantifiers, powers are function types, coends are existential quantifiers and copowers are product spaces. This only breaks down for our purposes when &lt;code&gt;g&lt;/code&gt; is contravariant, in which case they are flipped. For higher kinds, these constructions occur point-wise. So, we can break things down into four general cases, each with cases for each arity:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran0&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; *) a =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Ran0&lt;/span&gt; { ran0 :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. σ r =&amp;gt; (a ~&amp;gt; p r) -&amp;gt; f r }

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran1&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;j&lt;/span&gt; -&amp;gt; *) a b =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Ran1&lt;/span&gt; { ran1 :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. σ r =&amp;gt; (a ~&amp;gt; p r) -&amp;gt; f r b }

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RanOp0&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; *) a =&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; e. σ e =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RanOp0&lt;/span&gt; (a ~&amp;gt; p e) (f e)

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan0&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; *) a =&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; e. σ e =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan0&lt;/span&gt; (p e ~&amp;gt; a) (f e)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan1&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;j&lt;/span&gt; -&amp;gt; *) a b =&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; e. σ e =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan1&lt;/span&gt; (p e ~&amp;gt; a) (f e b)

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LanOp0&lt;/span&gt; σ p (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; *) a =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LanOp0&lt;/span&gt; { lan0 :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. σ r =&amp;gt; (p r -&amp;gt; a) -&amp;gt; f r }

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The more specific proposed (co)free definitions are:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;family&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;   :: (&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;) -&amp;gt; k -&amp;gt; k&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;family&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;) -&amp;gt; k -&amp;gt; k&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ a = &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;gratis0&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. σ &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt; σ f a = &lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;gratis1&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;. σ &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree0&lt;/span&gt; σ a = forall e. σ e =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree0&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) e&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Cofree0&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt; σ f a = forall g. σ g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; ~&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define some handly classes and instances for working with these types, several of which generalize existing Haskell concepts:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;j&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  comap :: (a ~&amp;gt; b) -&amp;gt; (f a ~&amp;gt; f b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  contramap :: (b ~&amp;gt; a) -&amp;gt; (f a ~&amp;gt; f b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure :: a ~&amp;gt; m a
  join :: m (m a) ~&amp;gt; m a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract :: w a ~&amp;gt; a
  split :: w a ~&amp;gt; w (w a)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Couniversal&lt;/span&gt; σ f | f -&amp;gt; σ &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  couniversal :: σ r =&amp;gt; (a ~&amp;gt; r) -&amp;gt; (f a ~&amp;gt; r)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Universal&lt;/span&gt; σ f | f -&amp;gt; σ &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  universal :: σ e =&amp;gt; (e ~&amp;gt; a) -&amp;gt; (e ~&amp;gt; f a)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  comap f (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; (e . (.f))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure x = &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; $ \k -&amp;gt; k x
  join (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; $ \k -&amp;gt; e $ \(&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; e) -&amp;gt; e k
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Couniversal&lt;/span&gt; σ (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  couniversal h (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; e) = e h

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only unfamiliar classes here should be &lt;code&gt;(Co)Universal&lt;/code&gt;. They are for witnessing the adjunctions that make &lt;code&gt;Free σ&lt;/code&gt; the initial &lt;code&gt;σ&lt;/code&gt; and &lt;code&gt;Cofree σ&lt;/code&gt; the final &lt;code&gt;σ&lt;/code&gt; in the relevant way. Only one direction is given, since the opposite is very easy to construct with the (co)monad structure.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Free σ&lt;/code&gt; is a monad and couniversal, &lt;code&gt;Cofree σ&lt;/code&gt; is a comonad and universal.&lt;/p&gt;
&lt;p&gt;We can now try to convince ourselves that &lt;code&gt;Free σ&lt;/code&gt; and &lt;code&gt;Cofree σ&lt;/code&gt; are absolute Here are some examples:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute0&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a))
               =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ a) &amp;lt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute0&lt;/span&gt; = (l, r)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
 l :: g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a
 l g = &lt;span class=&quot;hljs-type&quot;&gt;Ran0&lt;/span&gt; $ \k -&amp;gt; comap (couniversal $ remember0 . k) g

 r :: &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a -&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a)
 r (&lt;span class=&quot;hljs-type&quot;&gt;Ran0&lt;/span&gt; e) = e $ &lt;span class=&quot;hljs-type&quot;&gt;Forget0&lt;/span&gt; . pure

&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute1&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; (g :: * -&amp;gt; * -&amp;gt; *) σ a x. (&lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a))
               =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ a) x &amp;lt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a x
&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute1&lt;/span&gt; = (l, r)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
 l :: g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) x -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a x
 l g = &lt;span class=&quot;hljs-type&quot;&gt;Ran1&lt;/span&gt; $ \k -&amp;gt; comap (couniversal $ remember0 . k) $$ g

 r :: &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a x -&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) x
 r (&lt;span class=&quot;hljs-type&quot;&gt;Ran1&lt;/span&gt; e) = e $ &lt;span class=&quot;hljs-type&quot;&gt;Forget0&lt;/span&gt; . pure

&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute0Op&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a))
                 =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free0&lt;/span&gt; σ a) &amp;lt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RanOp&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;free0Absolute0Op&lt;/span&gt; = (l, r)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
 l :: g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RanOp&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a
 l = &lt;span class=&quot;hljs-type&quot;&gt;RanOp0&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Forget0&lt;/span&gt; . pure

 r :: &lt;span class=&quot;hljs-type&quot;&gt;RanOp&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a -&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a)
 r (&lt;span class=&quot;hljs-type&quot;&gt;RanOp0&lt;/span&gt; h g) = contramap (couniversal $ remember0 . h) g

&lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As can be seen, the definitions share a lot of structure. I'm quite confident that with the right building blocks these could be defined once for each of the four types of Kan extensions, with types like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;freeAbsolute&lt;/span&gt;
  :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a))
  =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a

&lt;span class=&quot;hljs-title&quot;&gt;cofreeAbsolute&lt;/span&gt;
  :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ a))
  =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ a) &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a

&lt;span class=&quot;hljs-title&quot;&gt;freeAbsoluteOp&lt;/span&gt;
  :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a))
  =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; σ a) &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RanOp&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a

&lt;span class=&quot;hljs-title&quot;&gt;cofreeAbsoluteOp&lt;/span&gt;
  :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g σ a. (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; g, σ (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ a))
  =&amp;gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; σ a) &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LanOp&lt;/span&gt; σ &lt;span class=&quot;hljs-type&quot;&gt;Forget&lt;/span&gt; g a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, it seems quite difficult to structure things in a way such that GHC will accept the definitions. I've successfully written &lt;code&gt;freeAbsolute&lt;/code&gt; using some axioms, but turning those axioms into class definitions and the like seems impossible.&lt;/p&gt;
&lt;p&gt;Anyhow, the punchline is that we can prove absoluteness using only the premise that there is a valid &lt;code&gt;σ&lt;/code&gt; instance for &lt;code&gt;Free σ&lt;/code&gt; and &lt;code&gt;Cofree σ&lt;/code&gt;. This tends to be quite easy; we just borrow the structure of the type we are quantifying over. This means that in all these cases, we are justified in saying that &lt;code&gt;Free σ ⊣ Forget σ ⊣ Cofree σ&lt;/code&gt;, and we have a very generic presentations of (co)free structures in Haskell. So let's look at some.&lt;/p&gt;
&lt;p&gt;We've already seen &lt;code&gt;Free Monoid&lt;/code&gt;, and last time we talked about &lt;code&gt;Free Applicative&lt;/code&gt;, and its relation to traversals. But, &lt;code&gt;Applicative&lt;/code&gt; is to traversal as &lt;code&gt;Functor&lt;/code&gt; is to lens, so it may be interesting to consider constructions on that. Both &lt;code&gt;Free Functor&lt;/code&gt; and &lt;code&gt;Cofree Functor&lt;/code&gt; make &lt;code&gt;Functor&lt;/code&gt;s:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Free1&lt;/span&gt; $ fmap f . e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt; h e) = &lt;span class=&quot;hljs-type&quot;&gt;Cofree1&lt;/span&gt; h (fmap f e)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And of course, they are (co)monads, covariant functors and (co)universal among &lt;code&gt;Functor&lt;/code&gt;s. But, it happens that I know some other types with these properties:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; f a = forall e. &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  comap f = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h e) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h (f $$ e)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; id
  join = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h (&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h' e)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; (h . h') e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h e) = &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; (f . h) e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Couniversal&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  couniversal tr = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; h e) -&amp;gt; fmap h (tr $$ e)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;oy&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Covariant&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  comap f = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; e) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; $ (f $$) . e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; e) -&amp;gt; e id
  split = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \(&lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; e) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; $ \k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; $ \k' -&amp;gt; e $ k' . k
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; $ \k -&amp;gt; e (k . f)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Universal&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  universal tr = &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ \e -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; $ \k -&amp;gt; tr $$ fmap k e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are the types involved in the (co-)Yoneda lemma. &lt;code&gt;CoYo&lt;/code&gt; is a monad, couniversal among functors, and &lt;code&gt;CoYo f&lt;/code&gt; is a &lt;code&gt;Functor&lt;/code&gt;. &lt;code&gt;Yo&lt;/code&gt; is a comonad, universal among functors, and is always a &lt;code&gt;Functor&lt;/code&gt;. So, are these equivalent types?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;coyoIso&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;CoYo&lt;/span&gt; &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;coyoIso&lt;/span&gt; = (&lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ couniversal pure, &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ couniversal pure)

&lt;span class=&quot;hljs-title&quot;&gt;yoIso&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Yo&lt;/span&gt; &amp;lt; ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;yoIso&lt;/span&gt; = (&lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ universal extract, &lt;span class=&quot;hljs-type&quot;&gt;Transform&lt;/span&gt; $ universal extract)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Indeed they are. And similar identities hold for the contravariant versions of these constructions.&lt;/p&gt;
&lt;p&gt;I don't have much of a use for this last example. I suppose to be perfectly precise, I should point out that these uses of &lt;code&gt;(Co)Yo&lt;/code&gt; are not actually part of the (co-)Yoneda lemma. They are two different constructions. The (co-)Yoneda lemma can be given in terms of Kan extensions as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;yoneda&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; f &amp;lt; ~&amp;gt; f

&lt;span class=&quot;hljs-title&quot;&gt;coyoneda&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; f &amp;lt; ~&amp;gt; f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, the use of &lt;code&gt;(Co)Yo&lt;/code&gt; to make &lt;code&gt;Functor&lt;/code&gt;s out of things that aren't necessarily is properly thought of in other terms. In short, we have some kind of category of Haskell types with only identity arrows---it is discrete. Then any type constructor, even non-functorial ones, is certainly a functor from said category (call it Haskrete) into the normal one (Hask). And there is an inclusion functor from Haskrete into Hask:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;             &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
 &lt;span class=&quot;hljs-type&quot;&gt;Haskrete&lt;/span&gt; -----&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Hask&lt;/span&gt;
      |        /|
      |       /
      |      /
&lt;span class=&quot;hljs-type&quot;&gt;Incl&lt;/span&gt;  |     /
      |    /  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt;/&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Incl&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
      |   /
      |  /
      v /
    &lt;span class=&quot;hljs-type&quot;&gt;Hask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, &lt;code&gt;(Co)Free Functor&lt;/code&gt; can also be thought of in terms of these Kan extensions involving the discrete category.&lt;/p&gt;
&lt;p&gt;To see more fleshed out, loadable versions of the code in this post, see &lt;a href=&quot;http://code.haskell.org/~dolio/haskell-share/categories-of-structures/COS.hs&quot;&gt;this file&lt;/a&gt;. I may also try a similar Agda development at a later date, as it may admit the more general absoluteness constructions easier.&lt;/p&gt;
&lt;p&gt;[0]: The reason for restricting ourselves to kinds involving only &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;(-&amp;gt;)&lt;/code&gt; is that they work much more simply than data kinds. Haskell values can't depend on type-level entities without using type classes. For *, this is natural, but for something like &lt;code&gt;Bool -&amp;gt; *&lt;/code&gt;, it is more natural for transformations to be able to inspect the booleans, and so should be something more like &lt;code&gt;forall b. InspectBool b =&amp;gt; f b -&amp;gt; g b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;[1]: First-class types are what you get by removing type families and synonyms from consideration. The reason for doing so is that these can't be used properly as parameters and the like, except in cases where they reduce to some other type that is first-class. For example, if we define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;I&lt;/span&gt; a = a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;even though GHC will report &lt;code&gt;I :: * -&amp;gt; *&lt;/code&gt;, it is not legal to write &lt;code&gt;Transform I I&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/categories-of-structures-in-haskell/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Skete: Exploring Distributed Package Management</title><link>https://comonad.com/reader/talks/youtube-gZwMp8YXIXg/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-gZwMp8YXIXg/</guid><pubDate>Wed, 20 May 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Alec Heller · 20 May 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;gZwMp8YXIXg&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gZwMp8YXIXg&quot;&gt;Watch on YouTube&lt;/a&gt; · 24 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;May 20, 2015 @ Bᴏsᴛᴏɴ Hᴀsᴋᴇʟʟ: &lt;a href=&quot;http://www.meetup.com/Boston-Haskell/events/219653513/&quot;&gt;http://www.meetup.com/Boston-Haskell/events/219653513/&lt;/a&gt;&lt;br&gt;
&quot;We thought it would be nice to have a completely local hackage. To this end we've spent the past few months experimenting with a new distributed package management system called Skete.  Our primary backend for Skete is based on Git. Using that, we've built a functional hackage repository. This combination allows us to keep a local copy of all of hackage in ~1GB of storage.  Additionally, Skete provides a clean approach to maintaining curated collections of packages (such as stackage) or private collections (such as internal company software or local forks) which can still be refreshed from upstream (public) repositories.&quot;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-gZwMp8YXIXg/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>How to Replace Failure by a Heap of Successes</title><link>https://comonad.com/reader/2015/heap-of-successes/</link><guid isPermaLink="false">https://comonad.com/reader/2015/heap-of-successes/</guid><pubDate>Sat, 02 May 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 2 May 2015&lt;/p&gt;&lt;p&gt;One problem that libraries like &lt;code&gt;pipes&lt;/code&gt; and &lt;code&gt;machines&lt;/code&gt; often have to deal with is the notion of &lt;a href=&quot;https://hackage.haskell.org/package/pipes-parse-3.0.2/docs/Pipes-Parse.html&quot;&gt;leftovers&lt;/a&gt;. What do you do with the stuff you haven't consumed? As parsers (and stream transducers) are usually implemented, we wind up losing contravariance on the input argument and/or we have to clutter our code with a separate type argument or transformer for handling leftovers. How can we do better?&lt;/p&gt;
&lt;p&gt;Danel Ahman and Tarmo Uustalu gave us a nice general theory of &lt;a href=&quot;http://homepages.inf.ed.ac.uk/s1225336/papers/types13postproc.pdf&quot;&gt;Update Monads&lt;/a&gt;. Today I want to go and tie that notion back to the idea of writing parsing combinators. I've been explaining this technique to folks since long before I'd ever heard the term &quot;update monad,&quot; but never took the time to write it up.&lt;/p&gt;
&lt;p&gt;Why now? I also then want to showcase a new way to exploit the limited structure of the updates to make a more efficient &lt;code&gt;Applicative&lt;/code&gt; for parsing, and also talk a bit about how this same general design can be used to address the issue of leftovers in streaming models.&lt;/p&gt;
&lt;h2 id=&quot;monoid-actions&quot;&gt;Monoid Actions&lt;/h2&gt;
&lt;p&gt;You can always update any state to any new (or old) state in the state monad. We have &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt; after all.&lt;/p&gt;
&lt;p&gt;Something like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;undo&lt;/span&gt; m = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  s &amp;lt;- get
  a &amp;lt;- m
  put s
  return a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will let us roll back to a previous state after we make a change, no matter what it is.&lt;/p&gt;
&lt;p&gt;But what if you want to restrict the space of updates you are allowed to make to the state? What if some actions should be irreversible or you are interested in a very small space of updates which can be expressed in tightly bounded space that is much smaller than the entire new state itself?&lt;/p&gt;
&lt;p&gt;An example where you might want an update to be irreversible is if you are keeping state about a bunch of file handles. Closing a file handle may affect that state, but you can't meaningfully &quot;reopen it&quot; just by reverting to a previous state involving the status of all of your file handles.&lt;/p&gt;
&lt;p&gt;In practice we usually try to hide the whole state from the user by not exporting it, and then providing a limited palette of operations we can perform on top of our now-opaque representation.&lt;/p&gt;
&lt;p&gt;This isn't the only option we have!&lt;/p&gt;
&lt;p&gt;Another way to do this is to define some language of updates and of how updates compose. The easiest such language to use that will fit nicely with the needs of a &lt;code&gt;Monad&lt;/code&gt; is to make it so a chain of such updates can be composed associatively, and such that there is a unit update. In other words, the right vocabulary for &quot;updating&quot; our state is probably a &lt;code&gt;Monoid&lt;/code&gt;. Then we need to figure out how to apply that &lt;code&gt;Monoid&lt;/code&gt; to our state.&lt;/p&gt;
&lt;p&gt;For this we can appeal to the notion of a (right) &lt;a href=&quot;http://en.wikipedia.org/wiki/Semigroup_action&quot;&gt;monoid action on a set&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That is to say we want:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; s m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act :: s -&amp;gt; m -&amp;gt; s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;such that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;act&lt;/span&gt; s mempty = s
&lt;span class=&quot;hljs-title&quot;&gt;act&lt;/span&gt; s (mappend m n) = act (act s m) n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this says is that the identity element changes nothing, and that the composition of monoid elements results in the composition of the effects on the state.&lt;/p&gt;
&lt;p&gt;The laws can be stated slightly more elegantly for left monoid actions, &lt;code&gt;m -&amp;gt; s -&amp;gt; s&lt;/code&gt;, where we can think of &lt;code&gt;act&lt;/code&gt; as monoid homomorphism from &lt;code&gt;m&lt;/code&gt; to &lt;code&gt;Endo s&lt;/code&gt;, but it is convenient to think of time as advancing to the right, so we'll stick to right monoid actions for now. Left monoid actions are discussed in a fairly practical setting in Brent Yorgey's very pleasant functional pearl &lt;a href=&quot;http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf&quot;&gt;Monoids: Themes and Variations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;update-vs--state&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;update-vs-state&quot;&gt;Update vs. State&lt;/h2&gt;
&lt;p&gt;So then what is an update monad?&lt;/p&gt;
&lt;p&gt;Well, let's consider the old fashioned state monad again:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runState&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This looks like a composition of two functors, &lt;code&gt;(-&amp;gt;) s&lt;/code&gt; and &lt;code&gt;(,) s&lt;/code&gt;, although the second is flipped, but it doesn't &lt;em&gt;act&lt;/em&gt; like the composition of reader and writer!&lt;/p&gt;
&lt;p&gt;The notion of an &lt;code&gt;Update&lt;/code&gt; monad came out of trying to find something that felt more like that composition.&lt;/p&gt;
&lt;p&gt;What if we break up the need for the two &lt;code&gt;s&lt;/code&gt;s to be the same? Done one way you get the Bob Atkey-style parameterized monad for State:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; i j a = &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runState&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;j&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is what we usually do, but another way to more loosely couple the types of the two &lt;code&gt;s&lt;/code&gt;'s is to take the update to be some answer in a &lt;code&gt;Monoid&lt;/code&gt; that has an action on our state.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; s m a = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runUpdate&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has the same type as above (except for the fact that I needlessly shuffled the pair), but we want to give it a completely different &lt;code&gt;Monad&lt;/code&gt;. Instead of a parameterized monad, we want a regular &lt;code&gt;Monad&lt;/code&gt;. Instead of matching indices, we're applying the updates to our state.&lt;/p&gt;
&lt;p&gt;The result you give back for how to manipulate the state is a mere update that has an appropriate monoid action on the state, rather than a whole new state:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; s m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \s -&amp;gt; (mempty, a)
  &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; ff &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; fa = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ff s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (m, f) -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; fa (act s m) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      (n, a) -&amp;gt; (mappend m n, f a)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; s m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \s -&amp;gt; (mempty, a)
  &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; f &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (m, a) -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; runUpdate (k a) (act s m) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      (n, b) -&amp;gt; (mappend m n, b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what examples might we come up with?&lt;/p&gt;
&lt;p&gt;We can always &lt;code&gt;get&lt;/code&gt; in an update monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;get&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \s -&amp;gt; (mempty, s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it is easy to define an action for &lt;code&gt;Endo s&lt;/code&gt; on &lt;code&gt;s&lt;/code&gt;. Using that choice of &lt;code&gt;Monoid&lt;/code&gt; lets us easily recover something with the full power of &lt;code&gt;State&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act s (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; f) = f s

&lt;span class=&quot;hljs-title&quot;&gt;put&lt;/span&gt; s = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \_ -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; (const s), ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also recover the power of &lt;code&gt;State&lt;/code&gt; by using &lt;code&gt;Last&lt;/code&gt; from &lt;code&gt;Data.Monoid&lt;/code&gt; with an appropriate action.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;Last&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act s (&lt;span class=&quot;hljs-type&quot;&gt;Last&lt;/span&gt; m) = fromMaybe s m

&lt;span class=&quot;hljs-title&quot;&gt;put&lt;/span&gt; s = &lt;span class=&quot;hljs-type&quot;&gt;Update&lt;/span&gt; $ \_ -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Last&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; s), ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can recover &lt;code&gt;Writer m&lt;/code&gt; with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; () m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act () m = ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or recover &lt;code&gt;Reader e&lt;/code&gt; with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; e () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act e () = e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a simple example, let's say you have a monotonically increasing counter for fresh variables. You could have the update language consist of how many times you bump the counter, the relative change, rather than the new counter value itself.&lt;/p&gt;
&lt;p&gt;Ahman and Uustalu have a bunch of other examples and we'll build one more below.&lt;/p&gt;
&lt;p&gt;As an aside: We can also derive a coupdate comonad. This can be useful for defining a variant notion of a lens where we restrict updates to updates that can be made in some monoidal language. This works because coupdate is analogous to the store comonad restricted to updates in some monoidal language. We might revisit that concept in a future post, but Danel Ahman and Tarmo Uustalu wrote up an &lt;a href=&quot;http://homepages.inf.ed.ac.uk/s1225336/papers/types14.pdf&quot;&gt;incredibly brief summary&lt;/a&gt; of them.&lt;/p&gt;
&lt;p&gt;Sadly, the MPTC for &lt;code&gt;RightMonoidAction&lt;/code&gt; is rather annoying to use in practice. We might want &lt;code&gt;RightMonoidAction m m&lt;/code&gt; for every &lt;code&gt;Monoid&lt;/code&gt;, but we likely also want &lt;code&gt;RightMonoidAction s (Endo s)&lt;/code&gt;, which results in overlap, incoherence and conflict. You can work around this to some extent with &lt;code&gt;newtype&lt;/code&gt; noise.&lt;/p&gt;
&lt;p&gt;Consequently, we won't actually be using the type given above, but we'll be applying it in spirit.&lt;/p&gt;
&lt;p&gt;One benefit of thinking in terms of update monads is that now you can expose all of the guts of your application, and nobody can violate your state change invariants anyways. This resolves the false dichotomy between &lt;a href=&quot;https://www.reddit.com/r/haskell/comments/2uoton/edward_kmett_encapsulation_vs_code_reuse/&quot;&gt;encapsulation and code reuse&lt;/a&gt; for this one application domain.&lt;/p&gt;
&lt;h2 id=&quot;a-list-of-successes&quot;&gt;A List of Successes&lt;/h2&gt;
&lt;p&gt;To keep the code approachable, I'll go back to the simplest and cleanest design of a parser I know. The title of this post is a riff on Philip Wadler's 1985 paper &lt;a href=&quot;https://rkrishnan.org/files/wadler-1985.pdf&quot;&gt;How to Replace Failure by a List of Successes&lt;/a&gt; in which he talked about a very straightforward example of a parser that works particularly well in a lazy language.&lt;/p&gt;
&lt;p&gt;So what does a &quot;list of successes&quot; parser look like?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runParser&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; [(&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;)] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Today we'd recognize it as just &lt;code&gt;StateT String []&lt;/code&gt;, but monad transformers didn't exist back then.&lt;/p&gt;
&lt;p&gt;To try to get away from arbitrary state, we should ask ourselves the question, &quot;what actions do we actually want to be able to apply to the &lt;code&gt;String&lt;/code&gt;?&quot;&lt;/p&gt;
&lt;p&gt;Well, a nice parser will only ever drop characters, so we could switch out the state &lt;code&gt;String&lt;/code&gt; for one with a monoid action on it such as&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; (a + b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightMonoidAction&lt;/span&gt; [a] &lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  act s (&lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt; n) = drop n s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: evil parsers that do things like push back input they haven't seen cause problems for parser combinators that avoid backtracking on consumption unless under &lt;code&gt;try&lt;/code&gt; and the like, such as Parsec, so this is a fairly sound assumption.&lt;/p&gt;
&lt;p&gt;This is just the &lt;code&gt;Sum Int&lt;/code&gt; monoid, with a carefully chosen action. The action is valid as long as we limit ourselves to non-negative drops in aggregate smaller than the maximum size of an &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we can consider the corresponding &quot;update monad transformer,&quot; which would give us something like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runParser&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; [(&lt;span class=&quot;hljs-type&quot;&gt;Drop&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But since we're using the notion of an update monad in spirit rather than in actuality we'll drop the newtype for &lt;code&gt;Drop&lt;/code&gt; and just use &lt;code&gt;Int&lt;/code&gt;. We'll agree to just &quot;think&quot; &lt;code&gt;Drop&lt;/code&gt; really hard when we see it in the future.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runParser&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; [(&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The one thing that we've really gained here is that we can know that no action randomly replaces the input string with another string. They all consume the same source.&lt;/p&gt;
&lt;p&gt;One win we could have, if &lt;code&gt;String&lt;/code&gt; was replaced by &lt;code&gt;ByteString&lt;/code&gt; (or &lt;code&gt;Text&lt;/code&gt;) here, is that you could exploit this to allow the user to recognize an identifier using any combination of actions and then &lt;code&gt;slice&lt;/code&gt; the &lt;code&gt;ByteString&lt;/code&gt; (or &lt;code&gt;Text&lt;/code&gt;) over the range that sub-parser matched. This would give you efficient sharing with the source, rather than breaking the input down into characters and then rebuilding a new bytestring that shares nothing. Slicing in &lt;code&gt;trifecta&lt;/code&gt; is done in this spirit, but on fingertrees of bytestrings instead.&lt;/p&gt;
&lt;p&gt;Moreover, we've gained something else critical. We've gained information about exactly how many characters we've consumed in a way that could let us work smarter for actions in the applicative and for &lt;code&gt;(&amp;gt;&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-heap-of-successes&quot;&gt;A Heap of Successes&lt;/h2&gt;
&lt;p&gt;If we grouped the results up by the &lt;code&gt;Int&lt;/code&gt; worth of characters we are dropping, this would tell us the offset of everything in that group, regardless of parse result.&lt;/p&gt;
&lt;p&gt;We could do this with something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runParser&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; [&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what we really want is cheap access to the next element, not random access so this sounds a lot more like a heap to me.&lt;/p&gt;
&lt;p&gt;We could go grab something like a pairing heap from an older post I wrote on &lt;a href=&quot;https://comonad.com/reader/2014/revisiting-matrix-multiplication-part-5/&quot;&gt;Heaps of Performance&lt;/a&gt;, or grab a more standard heap construction.&lt;/p&gt;
&lt;p&gt;For now, I'm going to punt on that and decide to proceed with a simple &lt;code&gt;[(Int, a)]&lt;/code&gt; representation where I maintain one invariant: The list is sorted by the number of elements we're dropping.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a = [(&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I'm referring to a heap for now, I'll be referring to a list in this form. A sorted list is a &lt;em&gt;unary&lt;/em&gt; heap replete with the heap property and everything, so I'm not even lying!&lt;/p&gt;
&lt;p&gt;Feel free to replace it with something with better performance characteristics, though.&lt;/p&gt;
&lt;p&gt;We can merge heaps:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- fair interleaving, because, well, why not? i guess we'll see.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; [] = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; aas@(a:&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) bbs@(b:bs)
  | fst a &amp;lt;= fst b = a : merge bbs &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
  | otherwise      = b : merge bs aas
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can &lt;code&gt;gather&lt;/code&gt; results by key.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;gather&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; [a]
&lt;span class=&quot;hljs-title&quot;&gt;gather&lt;/span&gt; [] = []
&lt;span class=&quot;hljs-title&quot;&gt;gather&lt;/span&gt; ((i0, a0) : as0) = go i0 [a0] as0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go i acc [] = [(i,acc)]
  go i acc ((j, a) : &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
    | i == j    = go i (a:acc) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
    | otherwise = (i, acc) : go j [a] &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, let's write a parser:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; i o = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runParser&lt;/span&gt; :: [&lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt; }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;State s a&lt;/code&gt; is neither covariant or contravariant in &lt;code&gt;s&lt;/code&gt;, because &lt;code&gt;s&lt;/code&gt; occurs in both positive and negative position, but we can parameterize the Parser covariantly on its input type, because unlike the usual &lt;code&gt;Parser&lt;/code&gt; we can make this a &lt;code&gt;Profunctor&lt;/code&gt;: The &lt;code&gt;i&lt;/code&gt; only occurs in negative position, and the &lt;code&gt;RightMonoidAction&lt;/code&gt; on the lists we read as input for &lt;code&gt;Drop&lt;/code&gt; doesn't care about the type parameter of the list.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ map (second g) . m . map f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we can start to see a bigger win when it comes to the &lt;code&gt;Applicative&lt;/code&gt; instance:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \_ -&amp;gt; [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,a)]
  &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; mf &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; ma = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s0 -&amp;gt; go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; s0 (gather (mf s0)) [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go i s ((j, fs) : fss) acc
      | s' &amp;lt;- drop (j-i) s = go j s' fss
                           $ merge acc
                           $ ma s' &amp;gt;&amp;gt;= \(k,a) -&amp;gt; fmap (\f -&amp;gt; (j+k,f a)) fs
    go _ _ [] acc = acc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the expression &lt;code&gt;m &amp;lt;*&amp;gt; n&lt;/code&gt;, the parser &lt;code&gt;n&lt;/code&gt; doesn't care about the value returned by &lt;code&gt;m&lt;/code&gt;. It only cares about how many characters it consumed. So what we do here is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, gather up all parses of the same length.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Starting with an empty heap as an accumulator, loop over the different lengths of parses in ascending order, dropping the delta from the previous drop from a working state, and feeding it to the second parser. When we're done we take the heap, shift everything in it by the number of elements we dropped to get there, and merge it with an accumulator.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Emit the accumulated heap.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  empty = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \_ -&amp;gt; []
  &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; m &amp;lt;|&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; n = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s -&amp;gt; m s `merge` n s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Alternative&lt;/code&gt; just merges the two result heaps.&lt;/p&gt;
&lt;p&gt;Turning to the &lt;code&gt;Monad&lt;/code&gt;, we don't get the benefits we had with &lt;code&gt;(&amp;lt;*&amp;gt;)&lt;/code&gt; in the &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; case. Subsequent parsing steps can now care about the values seen so far, so &lt;code&gt;gather&lt;/code&gt; doesn't help. We can still at least drive the subsequent parses by dropping incrementally, as before, though.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \_ -&amp;gt; [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,a)]
  &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; ma &amp;gt;&amp;gt;= amb = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s0 -&amp;gt; go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; s0 (ma s0) [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go i s ((j, a) : fss) acc
      | s' &amp;lt;- drop (j-i) s = go j s' fss
                           $ merge acc
                           $ (\(k,b) -&amp;gt; (j+k,b)) &amp;lt;$&amp;gt; runParser (amb a) s'
    go _ _ [] acc = acc
  (&amp;gt;&amp;gt;) = (*&amp;gt;)
  fail _ = empty
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mzero = empty
  mplus = (&amp;lt;|&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can go and write instances to make this compatible with the operations in my &lt;code&gt;parsers&lt;/code&gt; package:&lt;/p&gt;
&lt;p&gt;We can do basic parsing:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parsing&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- do or do not, there is no try&lt;/span&gt;
  try = id
  m &amp;lt;?&amp;gt; _ = m
  unexpected _ = empty
  eof = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    [] -&amp;gt; [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,())]
    _  -&amp;gt; []
  notFollowedBy (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s -&amp;gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; null (m s)
    &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,())]
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can recognize characters:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CharParsing&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  satisfy p = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    c:_ | p c -&amp;gt; [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,c)]
    _         -&amp;gt; []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this parser can gracefully support &lt;code&gt;lookAhead&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LookAheadParsing&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lookAhead (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \s -&amp;gt; first (const &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &amp;lt;$&amp;gt; m s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can write a helper combinator that converts to a more traditional &quot;list of successes&quot; form.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; i o -&amp;gt; [i] -&amp;gt; [(o, [i])]
&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; m) s0 = go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; s0 (m s0) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go i s ((j,o):xs) | s' &amp;lt;- drop (j-i) s = (o,s') : go j s' xs
  go _ _ [] = []
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;Update&lt;/code&gt; monad conversion isn't free. Left associated binds in an &lt;code&gt;Update&lt;/code&gt; monad now apply two different actions to the same source, whereas normally we apply the two actions in series. Compare&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(drop &lt;span class=&quot;hljs-number&quot;&gt;10000&lt;/span&gt; s, drop (&lt;span class=&quot;hljs-number&quot;&gt;10000&lt;/span&gt;+&lt;span class=&quot;hljs-number&quot;&gt;123&lt;/span&gt;) s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;let&lt;/span&gt; s' = drop &lt;span class=&quot;hljs-number&quot;&gt;10000&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; (s', drop &lt;span class=&quot;hljs-number&quot;&gt;123&lt;/span&gt; s')`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You'd generally rather have the latter, so &lt;code&gt;State&lt;/code&gt; still has a reason to exist!&lt;/p&gt;
&lt;p&gt;Here we mitigate that to some extent by gathering all of our updates in a particular order that lets us share some work between them to reduce this cost when working across multiple results, but we still run into this for left associated binds.&lt;/p&gt;
&lt;p&gt;There are several workarounds an update monad might employ to control for this phenomenon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We could also work around this by hitting this with the &lt;code&gt;Codensity&lt;/code&gt; monad to &lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less/&quot;&gt;force everything into right association&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Or we can work smarter by finding a better representation for our set or Monoid. For example, if we had a cheaper drop by using &lt;a href=&quot;https://comonad.com/reader/2015/fibonacci-leonardo/&quot;&gt;Leonardo&lt;/a&gt; or &lt;a href=&quot;https://comonad.com/reader/2015/online-lca/#skew-binary&quot;&gt;skew-binary&lt;/a&gt; random access lists to reduce it to &lt;em&gt;O(log n)&lt;/em&gt;, then we could greatly reduce the costs of applying our monoid action.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;on-leftovers&quot;&gt;On Leftovers&lt;/h2&gt;
&lt;p&gt;Given the structure above, we &lt;em&gt;could&lt;/em&gt; define a &lt;code&gt;Category&lt;/code&gt; for parsing with (in part)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Category&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id = &lt;span class=&quot;hljs-type&quot;&gt;Parser&lt;/span&gt; $ \ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt;
    a:_ -&amp;gt; [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,a)]
    _   -&amp;gt; []
  ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can drive &lt;code&gt;(f . g)&lt;/code&gt; by having the right parser consume input and spit out a single output token, and repeating to generate a lexer that generates tokens consumed by the next parser. This is problematic though, we're generating a list of lists of tokens due to the non-determinism possible in the lexing phase, and they share prefixes, not suffixes. This is much better served by switching away from the simple parser model we have here where we know everything up front, and instead starting to talk about something like a &lt;code&gt;Conduit&lt;/code&gt;, &lt;code&gt;Iteratee&lt;/code&gt;, &lt;code&gt;Pipe&lt;/code&gt; or &lt;code&gt;Machine&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exercise:&lt;/em&gt; Why can't we have &lt;code&gt;Arrow&lt;/code&gt;, &lt;code&gt;Strong&lt;/code&gt;, &lt;code&gt;Choice&lt;/code&gt;, etc?&lt;/p&gt;
&lt;p&gt;Now, I don't like leftovers. This same mechanism whereby we spot the fact that we are only doing a limited form of update (e.g. dropping) extends to scrapping &quot;leftovers&quot; from these streaming models as well as models where we know the entire state up front. We just need an appropriate notion of &quot;action&quot;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;To get here what did we do? We used the fact that an update monad can have a smaller, simpler update language than a &lt;code&gt;State&lt;/code&gt; monad. Then we took an existing &lt;code&gt;StateT&lt;/code&gt;-based monad for parsing and converted it to an appropriate &lt;code&gt;UpdateT&lt;/code&gt; monad. Afterwards we realized we could impose an invariant on the order it gave back its results in the list to gather up like updates and enable us to have a more efficient &lt;code&gt;Applicative&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I leave as an exercise the task of swapping out &lt;code&gt;[(Int, a)]&lt;/code&gt; for a min-heap. We don't need to maintain a full sorted list. We can punt the task of sorting to a heap.&lt;/p&gt;
&lt;p&gt;I also leave as an exercise how to extract the proper leftmost parse first. &lt;code&gt;merge&lt;/code&gt; being needlessly fair destroyed this property along with the truth of the &lt;code&gt;Monad&lt;/code&gt; laws (unless you quotient out the order in which you get results). Heaps will also destroy this property without some extra tagging to help resolve ties. &lt;code&gt;gather&lt;/code&gt; also needs to reverse the accumulators to ensure this property holds. I'm not bothering with either of these things in the code above.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exercise:&lt;/em&gt; Why would we need to tag? How could we do it?&lt;/p&gt;
&lt;p&gt;Moreover, I've only converted a fairly simple parser to this format above. Doing so with proper error handling is a more complex affair.&lt;/p&gt;
&lt;p&gt;I've collapsed the code above into a single &lt;a href=&quot;https://gist.github.com/ekmett/578eaf3e5a37f7315e6c&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;May 1, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/heap-of-successes/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Domains, Sets, Traversals and Applicatives</title><link>https://comonad.com/reader/2015/domains-sets-traversals-and-applicatives/</link><guid isPermaLink="false">https://comonad.com/reader/2015/domains-sets-traversals-and-applicatives/</guid><pubDate>Wed, 29 Apr 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 29 April 2015&lt;/p&gt;&lt;p&gt;Last time I looked at free monoids, and noticed that in Haskell lists don't really cut it. This is a consequence of laziness and general recursion. To model a language with those properties, one needs to use domains and monotone, continuous maps, rather than sets and total functions (a call-by-value language with general recursion would use domains and strict maps instead).&lt;/p&gt;
&lt;p&gt;This time I'd like to talk about some other examples of this, and point out how doing so can (perhaps) resolve some disagreements that people have about the specific cases.&lt;/p&gt;
&lt;p&gt;The first example is not one that I came up with: induction. It's sometimes said that Haskell does not have inductive types at all, or that we cannot reason about functions on its data types by induction. However, I think this is (techincally) inaccurate. What's true is that we cannot simply pretend that that our types are sets and use the induction principles for sets to reason about Haskell programs. Instead, one has to figure out what inductive domains would be, and what their proof principles are.&lt;/p&gt;
&lt;p&gt;Fortunately, there are some papers about doing this. The most recent (that I'm aware of) is &lt;a href=&quot;http://arxiv.org/pdf/1206.0357.pdf&quot;&gt;Generic Fibrational Induction&lt;/a&gt;. I won't get too into the details, but it shows how one can talk about induction in a general setting, where one has a category that roughly corresponds to the type theory/programming language, and a second category of proofs that is 'indexed' by the first category's objects. Importantly, it is not required that the second category is somehow 'part of' the type theory being reasoned about, as is often the case with dependent types, although that is also a special case of their construction.&lt;/p&gt;
&lt;p&gt;One of the results of the paper is that this framework can be used to talk about induction principles for types that don't make sense as sets. Specifically:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Hyp&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Hyp&lt;/span&gt; ((&lt;span class=&quot;hljs-type&quot;&gt;Hyp&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the type of &quot;hyperfunctions&quot;. Instead of interpreting this type as a set, where it would effectively require a set that is isomorphic to the power set of its power set, they interpret it in the category of domains and strict functions mentioned earlier. They then construct the proof category in a similar way as one would for sets, except instead of talking about predicates as sub&lt;em&gt;sets&lt;/em&gt;, we talk about sub-&lt;em&gt;domains&lt;/em&gt; instead. Once this is done, their framework gives a notion of induction for this type.&lt;/p&gt;
&lt;p&gt;This example is suitable for ML (and suchlike), due to the strict functions, and sort of breaks the idea that we can really get away with only thinking about sets, even there. Sets are good enough for some simple examples (like flat domains where we don't care about ⊥), but in general we have to generalize induction itself to apply to all types in the 'good' language.&lt;/p&gt;
&lt;p&gt;While I haven't worked out how the generic induction would work out for Haskell, I have little doubt that it would, because ML actually contains all of Haskell's data types (and vice versa). So the fact that the framework gives meaning to induction for ML implies that it does so for Haskell. If one wants to know what induction for Haskell's 'lazy naturals' looks like, they can study the ML analogue of:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LNat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (() -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LNat&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;because function spaces lift their codomain, and make things 'lazy'.&lt;/p&gt;
&lt;p&gt;----&lt;/p&gt;
&lt;p&gt;The other example I'd like to talk about hearkens back to the previous article. I explained how &lt;code&gt;foldMap&lt;/code&gt; is the proper fundamental method of the &lt;code&gt;Foldable&lt;/code&gt; class, because it can be massaged to look like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foldMap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FreeMonoid&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and lists are not the free monoid, because they do not work properly for various infinite cases.&lt;/p&gt;
&lt;p&gt;I also mentioned that &lt;code&gt;foldMap&lt;/code&gt; looks a lot like &lt;code&gt;traverse&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foldMap&lt;/span&gt;  :: (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; t   , &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m)      =&amp;gt; (a -&amp;gt; m)   -&amp;gt; t a -&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;traverse&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f) =&amp;gt; (a -&amp;gt; f b) -&amp;gt; t a -&amp;gt; f (t b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And of course, we have &lt;code&gt;Monoid m =&amp;gt; Applicative (Const m)&lt;/code&gt;, and the functions are expected to agree in this way when applicable.&lt;/p&gt;
&lt;p&gt;Now, people like to get in arguments about whether traversals are allowed to be infinite. I know Ed Kmett likes to argue that they can be, because he has lots of examples. But, not everyone agrees, and especially people who have papers proving things about traversals tend to side with the finite-only side. I've heard this includes one of the inventors of &lt;code&gt;Traversable&lt;/code&gt;, Conor McBride.&lt;/p&gt;
&lt;p&gt;In my opinion, the above disagreement is just another example of a situation where we have a generic notion instantiated in two different ways, and intuition about one does not quite transfer to the other. If you are working in a language like Agda or Coq (for proving), you will be thinking about traversals in the context of sets and total functions. And there, traversals are finite. But in Haskell, there are infinitary cases to consider, and they should work out all right when thinking about domains instead of sets. But I should probably put forward some argument for this position (and even if I don't need to, it leads somewhere else interesting).&lt;/p&gt;
&lt;p&gt;One example that people like to give about finitary traversals is that they can be done via lists. Given a finite traversal, we can traverse to get the elements (using &lt;code&gt;Const [a]&lt;/code&gt;), traverse the list, then put them back where we got them by traversing again (using &lt;code&gt;State [a]&lt;/code&gt;). Usually when you see this, though, there's some subtle cheating in relying on the list to be exactly the right length for the second traversal. It will be, because we got it from a traversal of the same structure, but I would expect that proving the function is actually total to be a lot of work. Thus, I'll use this as an excuse to do my own cheating later.&lt;/p&gt;
&lt;p&gt;Now, the above uses lists, but why are we using lists when we're in Haskell? We know they're deficient in certain ways. It turns out that we can give a lot of the same relevant structure to the better free monoid type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) -&amp;gt; m) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure x = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; ($ x)
  &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; ef &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; ex = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \k -&amp;gt; ef $ \f -&amp;gt; ex $ \x -&amp;gt; k (f x)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \_ -&amp;gt; mempty
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; l) (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; r) = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \k -&amp;gt; l k &amp;lt;&amp;gt; r k
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; e) = e f

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; f b = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unAp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; $ pure mempty
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; l) (&lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; r) = &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; $ (&amp;lt;&amp;gt;) &amp;lt; $&amp;gt; l &amp;lt; *&amp;gt; r
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; e) = unAp . e $ &lt;span class=&quot;hljs-type&quot;&gt;Ap&lt;/span&gt; . fmap pure . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, free monoids are &lt;code&gt;Monoids&lt;/code&gt; (of course), &lt;code&gt;Foldable&lt;/code&gt;, and even &lt;code&gt;Traversable&lt;/code&gt;. At least, we can define something with the right type that wouldn't bother anyone if it were written in a total language with the right features, but in Haskell it happens to allow various infinite things that people don't like.&lt;/p&gt;
&lt;p&gt;Now it's time to cheat. First, let's define a function that can take any &lt;code&gt;Traversable&lt;/code&gt; to our free monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;toFreeMonoid&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t =&amp;gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;toFreeMonoid&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \k -&amp;gt; getConst $ traverse (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; . k) f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let's define a &lt;code&gt;Monoid&lt;/code&gt; that's not a monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cheat&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Single&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Append&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cheat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Cheat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cheat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt;
  mappend = &lt;span class=&quot;hljs-type&quot;&gt;Append&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may recognize this as the data version of the free monoid from the previous article, where we get the real free monoid by taking a quotient. using this, we can define an &lt;code&gt;Applicative&lt;/code&gt; that's not valid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; b a =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; { prosper :: &lt;span class=&quot;hljs-type&quot;&gt;Cheat&lt;/span&gt; b -&amp;gt; a } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure x = &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; $ \_ -&amp;gt; x

  &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; f &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; $ \c -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; c &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Append&lt;/span&gt; l r -&amp;gt; f l (x r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given these building blocks, we can define a function to relabel a traversable using a free monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;relabel&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t =&amp;gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; b -&amp;gt; t b
&lt;span class=&quot;hljs-title&quot;&gt;relabel&lt;/span&gt; t (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; m) = propser (traverse (const hope) t) (m &lt;span class=&quot;hljs-type&quot;&gt;Single&lt;/span&gt;)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
 hope = &lt;span class=&quot;hljs-type&quot;&gt;Cheating&lt;/span&gt; $ \c -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; c &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;Single&lt;/span&gt; x -&amp;gt; x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can implement any traversal by taking a trip through the free monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;slowTraverse&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t) =&amp;gt; (a -&amp;gt; f b) -&amp;gt; t a -&amp;gt; f (t b)
&lt;span class=&quot;hljs-title&quot;&gt;slowTraverse&lt;/span&gt; f t = fmap (relabel t) . traverse f . toFreeMonoid $ t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And since we got our free monoid via traversing, all the partiality I hid in the above won't blow up in practice, rather like the case with lists and finite traversals.&lt;/p&gt;
&lt;p&gt;Arguably, this is worse cheating. It relies on the exact association structure to work out, rather than just number of elements. The reason is that for infinitary cases, you cannot flatten things out, and there's really no way to detect when you have something infinitary. The finitary traversals have the luxury of being able to reassociate everything to a canonical form, while the infinite cases force us to not do any reassociating at all. So this might be somewhat unsatisfying.&lt;/p&gt;
&lt;p&gt;But, what if we didn't have to cheat at all? We can get the free monoid by tweaking &lt;code&gt;foldMap&lt;/code&gt;, and it looks like &lt;code&gt;traverse&lt;/code&gt;, so what happens if we do the same manipulation to the latter?&lt;/p&gt;
&lt;p&gt;It turns out that lens has a type for this purpose, a slight specialization of which is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; { runBazaar :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f t }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using this type, we can reorder &lt;code&gt;traverse&lt;/code&gt; to get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;howBizarre&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t =&amp;gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b (t b)
&lt;span class=&quot;hljs-title&quot;&gt;howBizarre&lt;/span&gt; t = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \k -&amp;gt; traverse k t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now, what do we do with this? And what even is it? [1]&lt;/p&gt;
&lt;p&gt;If we continue drawing on intuition from &lt;code&gt;Foldable&lt;/code&gt;, we know that &lt;code&gt;foldMap&lt;/code&gt; is related to the free monoid. &lt;code&gt;Traversable&lt;/code&gt; has more indexing, and instead of &lt;code&gt;Monoid&lt;/code&gt; uses &lt;code&gt;Applicative&lt;/code&gt;. But the latter are actually related to the former; &lt;code&gt;Applicative&lt;/code&gt;s are monoidal (closed) functors. And it turns out, &lt;code&gt;Bazaar&lt;/code&gt; has to do with free &lt;code&gt;Applicative&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;If we want to construct free &lt;code&gt;Applicative&lt;/code&gt;s, we can use our universal property encoding trick:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p f a =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; { gratis :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; g. p g =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; x. f x -&amp;gt; g x) -&amp;gt; g a }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a higher-order version of the free &lt;code&gt;p&lt;/code&gt;, where we parameterize over the constraint we want to use to represent structures. So &lt;code&gt;Free Applicative f&lt;/code&gt; is the free &lt;code&gt;Applicative&lt;/code&gt; over a type constructor &lt;code&gt;f&lt;/code&gt;. I'll leave the instances as an exercise.&lt;/p&gt;
&lt;p&gt;Since free monoid is a monad, we'd expect &lt;code&gt;Free p&lt;/code&gt; to be a monad, too. In this case, it is a McBride style indexed monad, as seen in &lt;a href=&quot;https://personal.cis.strath.ac.uk/conor.mcbride/Kleisli.pdf&quot;&gt;The Kleisli Arrows of Outrageous Fortune&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; f ~&amp;gt; g = forall x. f x -&amp;gt; g x&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;embed&lt;/span&gt; :: f ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p f
&lt;span class=&quot;hljs-title&quot;&gt;embed&lt;/span&gt; fx = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; $ \k -&amp;gt; k fx

&lt;span class=&quot;hljs-title&quot;&gt;translate&lt;/span&gt; :: (f ~&amp;gt; g) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p f ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p g
&lt;span class=&quot;hljs-title&quot;&gt;translate&lt;/span&gt; tr (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; $ \k -&amp;gt; e (k . tr)

&lt;span class=&quot;hljs-title&quot;&gt;collapse&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p f) ~&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; p f
&lt;span class=&quot;hljs-title&quot;&gt;collapse&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; $ \k -&amp;gt; e $ \(&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; e') -&amp;gt; e' k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That paper explains how these are related to Atkey style indexed monads:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt; key i j &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt; :: key -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt; key i i

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; m i j a = m (&lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;j&lt;/span&gt;) i&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;ireturn&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IMonad&lt;/span&gt; m =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; m i i a
&lt;span class=&quot;hljs-title&quot;&gt;ireturn&lt;/span&gt; = ...

&lt;span class=&quot;hljs-title&quot;&gt;ibind&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IMonad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; m i j a -&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; m j k b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; m i k b
&lt;span class=&quot;hljs-title&quot;&gt;ibind&lt;/span&gt; = ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out, &lt;code&gt;Bazaar&lt;/code&gt; is exactly the Atkey indexed monad derived from the &lt;code&gt;Free Applicative&lt;/code&gt; indexed monad (with some arguments shuffled) [2]:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;hence&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt;) t b a
&lt;span class=&quot;hljs-title&quot;&gt;hence&lt;/span&gt; bz = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; $ \tr -&amp;gt; runBazaar bz $ tr . &lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;forth&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Atkey&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt;) t b a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t
&lt;span class=&quot;hljs-title&quot;&gt;forth&lt;/span&gt; fa = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \g -&amp;gt; gratis fa $ \(&lt;span class=&quot;hljs-type&quot;&gt;At&lt;/span&gt; a) -&amp;gt; g a

&lt;span class=&quot;hljs-title&quot;&gt;imap&lt;/span&gt; :: (a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a i j -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; b i j
&lt;span class=&quot;hljs-title&quot;&gt;imap&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \k -&amp;gt; e (k . f)

&lt;span class=&quot;hljs-title&quot;&gt;ipure&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a i i
&lt;span class=&quot;hljs-title&quot;&gt;ipure&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; ($ x)

(&amp;gt;&amp;gt;&amp;gt;=) :: &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a j i -&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; b k j) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; b k i
&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e &amp;gt;&amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \k -&amp;gt; e $ \x -&amp;gt; runBazaar (f x) k

(&amp;gt;==&amp;gt;) :: (s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; i o t) -&amp;gt; (i -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b o) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t
(f &amp;gt;==&amp;gt; g) x = f x &amp;gt;&amp;gt;&amp;gt;= g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an aside, &lt;code&gt;Bazaar&lt;/code&gt; is also an (Atkey) indexed comonad, and the one that characterizes traversals, similar to how indexed store characterizes lenses. A &lt;code&gt;Lens s t a b&lt;/code&gt; is equivalent to a coalgebra &lt;code&gt;s -&amp;gt; Store a b t&lt;/code&gt;. A traversal is a similar &lt;code&gt;Bazaar&lt;/code&gt; coalgebra:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t
    ~
  s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f t
    ~
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; s -&amp;gt; f t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It so happens that Kleisli composition of the Atkey indexed monad above &lt;code&gt;(&amp;gt;==&amp;gt;)&lt;/code&gt; is traversal composition.&lt;/p&gt;
&lt;p&gt;Anyhow, &lt;code&gt;Bazaar&lt;/code&gt; also inherits &lt;code&gt;Applicative&lt;/code&gt; structure from &lt;code&gt;Free Applicative&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \k -&amp;gt; fmap f (e k)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure x = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \_ -&amp;gt; pure x
  &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; ef &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; ex = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; $ \k -&amp;gt; ef k &amp;lt; *&amp;gt; ex k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is actually analogous to the &lt;code&gt;Monoid&lt;/code&gt; instance for the free monoid; we just delegate to the underlying structure.&lt;/p&gt;
&lt;p&gt;The more exciting thing is that we can fold and traverse over the first argument of &lt;code&gt;Bazaar&lt;/code&gt;, just like we can with the free monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bfoldMap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; (a -&amp;gt; m) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t -&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;bfoldMap&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e) = getConst $ e (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; . f)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; g f a = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getComp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; . pure . pure
  &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; f &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; $ liftA2 (&amp;lt; *&amp;gt;) f x

&lt;span class=&quot;hljs-title&quot;&gt;btraverse&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f) =&amp;gt; (a -&amp;gt; f a') -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a b t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; a' b t
&lt;span class=&quot;hljs-title&quot;&gt;btraverse&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e) = getComp $ e (c . fmap ipure . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is again analogous to the free monoid code. &lt;code&gt;Comp&lt;/code&gt; is the analogue of &lt;code&gt;Ap&lt;/code&gt;, and we use &lt;code&gt;ipure&lt;/code&gt; in &lt;code&gt;traverse&lt;/code&gt;. I mentioned that &lt;code&gt;Bazaar&lt;/code&gt; is a comonad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; b b t -&amp;gt; t
&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; e) = runIdentity $ e &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now we are finally prepared to not cheat:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;honestTraverse&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t) =&amp;gt; (a -&amp;gt; f b) -&amp;gt; t a -&amp;gt; f (t b)
&lt;span class=&quot;hljs-title&quot;&gt;honestTraverse&lt;/span&gt; f = fmap extract . btraverse f . howBizarre
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, we can traverse by first turning out &lt;code&gt;Traversable&lt;/code&gt; into some structure that's kind of like the free monoid, except having to do with &lt;code&gt;Applicative&lt;/code&gt;, traverse that, and then pull a result back out. &lt;code&gt;Bazaar&lt;/code&gt; retains the information that we're eventually building back the same type of structure, so we don't need any cheating.&lt;/p&gt;
&lt;p&gt;To pull this back around to domains, there's nothing about this code to object to if done in a total language. But, if we think about our free &lt;code&gt;Applicative&lt;/code&gt;-ish structure, in Haskell, it will naturally allow infinitary expressions composed of the &lt;code&gt;Applicative&lt;/code&gt; operations, just like the free monoid will allow infinitary monoid expressions. And this is okay, because &lt;em&gt;some&lt;/em&gt; &lt;code&gt;Applicative&lt;/code&gt;s can make sense of those, so throwing them away would make the type not free, in the same way that even finite lists are not the free monoid in Haskell. And this, I think, is compelling enough to say that infinite traversals are right for Haskell, just as they are wrong for Agda.&lt;/p&gt;
&lt;p&gt;For those who wish to see executable code for all this, I've put a files &lt;a href=&quot;http://code.haskell.org/~dolio/haskell-share/FMon.hs&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://code.haskell.org/~dolio/haskell-share/Libre.hs&quot;&gt;here&lt;/a&gt;. The latter also contains some extra goodies at the end that I may talk about in further installments.&lt;/p&gt;
&lt;p&gt;[1] Truth be told, I'm not exactly sure.&lt;/p&gt;
&lt;p&gt;[2] It turns out, you can generalize &lt;code&gt;Bazaar&lt;/code&gt; to have a correspondence for every choice of &lt;code&gt;p&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizarre&lt;/span&gt; p a b t =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Bizarre&lt;/span&gt; { bizarre :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. p f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f t }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;hence&lt;/code&gt; and &lt;code&gt;forth&lt;/code&gt; above go through with the more general types. This can be seen &lt;a href=&quot;http://code.haskell.org/~dolio/haskell-share/Libre.hs&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/domains-sets-traversals-and-applicatives/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Fibonacci — Part 1: Leonardo Random Access Lists</title><link>https://comonad.com/reader/2015/fibonacci-leonardo/</link><guid isPermaLink="false">https://comonad.com/reader/2015/fibonacci-leonardo/</guid><pubDate>Tue, 28 Apr 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 28 April 2015&lt;/p&gt;&lt;p&gt;Chris Okasaki wrote about many data structures in his excellent book &lt;a href=&quot;http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504&quot;&gt;&quot;Purely Functional Data Structures&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Today I have the rare opportunity to talk about (invent?) one that he didn't. It doesn't achieve anything
new in this space, but it is an interesting rearrangement of parts folks already knew for other things.&lt;/p&gt;
&lt;h2 id=&quot;leonardo-numbers&quot;&gt;Leonardo Numbers&lt;/h2&gt;
&lt;p&gt;The &quot;Leonardo&quot; numbers are given by &lt;a href=&quot;https://oeis.org/A001595&quot;&gt;1,1,3,5,9,15,25,41...&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This arises from a recurrence:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;leonardo&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;leonardo&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;leonardo&lt;/span&gt; n = leonardo (n - &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) + leonardo (n - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just a slight mutation of the usual Fibonacci recurrence, where we add an extra 1 at each step.&lt;/p&gt;
&lt;p&gt;(Fibonacci was named Leonardo Bonacci.)&lt;/p&gt;
&lt;p&gt;We can read the recurrence formula forwards:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;next&lt;/span&gt; i j = i + j + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or backwards&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;prev&lt;/span&gt; i j = j - i - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can take multiple steps given a sequence of Leonardo numbers. Given &lt;code&gt;...g,h,i,j..&lt;/code&gt; you can compute &lt;code&gt;g&lt;/code&gt; from &lt;code&gt;i&lt;/code&gt; and &lt;code&gt;j&lt;/code&gt; directly, just by expanding:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;prev2&lt;/span&gt; i j = prev (prev i j) i
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;prev2&lt;/span&gt; i j = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;*i - j
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can compute the n_th_ Leonardo number in &lt;code&gt;O(log n)&lt;/code&gt; time, just like the Fibonacci numbers, or any similar linear recurrence relation.&lt;/p&gt;
&lt;p&gt;They are in fact, intimately related to the Fibonacci numbers:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;leonardo&lt;/span&gt; n = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * fibonacci (n+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We know &lt;code&gt;leonardo 0 = leonardo 1 = 1&lt;/code&gt;, but after that the positive Leonardo numbers are unique.&lt;/p&gt;
&lt;p&gt;By the recurrence, &lt;code&gt;leonardo (-1) = prev 1 1 = -1&lt;/code&gt;. We can continue to define negative Leonardo numbers analogous to negative Fibonacci numbers.&lt;/p&gt;
&lt;p&gt;Regardless, to exploit any of the recurrences above, to walk forward or backwards from some current Leonardo number, it is highly beneficial to
keep around the previous (or next) one. You can think of this pair as a cursor through the list of Leonardo numbers.&lt;/p&gt;
&lt;p&gt;Dijkstra has a lot more to say on the subject of Leonardo numbers in &lt;a href=&quot;http://www.cs.utexas.edu/users/EWD/transcriptions/EWD07xx/EWD797.html&quot;&gt;EWD797&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;building-a-data-structure&quot;&gt;Building a Data Structure&lt;/h2&gt;
&lt;p&gt;Okasaki, Knuth and others teach us to think of data structures from number systems or recurrences like this and I'm definitely not the first to play around with using the Leonardo numbers in this fashion.&lt;/p&gt;
&lt;p&gt;The first use of Leonardo numbers in the shape of a data structure that I am aware of is the heap shape in Dijkstra's &quot;smoothsort,&quot; defined in &lt;a href=&quot;http://www.cs.utexas.edu/users/EWD/transcriptions/EWD07xx/EWD796a.html&quot;&gt;EWD796a&lt;/a&gt; from which I first learned the name of the sequence. We'll revisit that in a bit.&lt;/p&gt;
&lt;p&gt;A Leonardo number adds one to the previous two Leonardo numbers. When we recast this as a data structure, it sounds like a biased tree.&lt;/p&gt;
&lt;p&gt;But the property of Leonardo numbers that grabs my attention is that you have two trees &quot;plus one new element&quot;. This sounds a lot like the structure of skew binary.&lt;/p&gt;
&lt;p&gt;So this invited the question:&lt;/p&gt;
&lt;p&gt;Can you build an efficient random access list structure using the Leonardo numbers, rather than skew binary?&lt;/p&gt;
&lt;p&gt;It turns out the answer is yes.&lt;/p&gt;
&lt;h2 id=&quot;lopsided-trees&quot;&gt;Lopsided Trees&lt;/h2&gt;
&lt;p&gt;We'll need some lopsided binary trees&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll internally maintain the invariant that all of our trees are some Leonardo number in size, with the left and right children having the previous 2 Leonardo numbers worth of children respectively. I'll leave it as an exercise to the folks in the crowd who love dependent types to enforce this invariant in their code, and just assume this invariant from here out.&lt;/p&gt;
&lt;p&gt;E.g. a tree of size 5 has a left child of size 1, and a right child of size 3:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  1
  +---,
  |   |
  2   3
      +----,
      |    |
      4    5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;while a tree of size 9 has a left child of size 3 and a right child of size 5:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  1
  +-------+
  |       |
  2       5
  +---,   +---,
  |   |   |   |
  3   4   6   7
              +---,
              |   |
              8   9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can show that the height of the tree grows logarithmically with the number of elements despite the skew.&lt;/p&gt;
&lt;p&gt;We'll delegate tracking the sizes of the trees to the next part.&lt;/p&gt;
&lt;h2 id=&quot;growing-a-spine&quot;&gt;Growing a Spine&lt;/h2&gt;
&lt;p&gt;We need a &quot;spine&quot; for the structure, analogous to the skew binary random access list, but now cluttered with a couple of extra numbers.&lt;/p&gt;
&lt;p&gt;If given a Leonardo number n, if &lt;code&gt;leonardo i = n&lt;/code&gt;, with i &amp;gt;= 0, I'll say that n has index i. Since 1 occurs twice, 1 has both index 0 and 1.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each tree we cons onto the spine will be associated with some Leonardo number, and we'll keep the previous Leonardo number as well to facilitate walking the trees and merging nodes later. We maintain the invariant that the sequence of Leonardo numbers we use has not just a series of increasing indices, but other than possibly the two trees present that have the smallest indices, there are no Leonardo numbers with with adjacent indices in the spine.&lt;/p&gt;
&lt;p&gt;This prevents the representation from being ambiguous, forcing us to use a tree of size 5 instead of the sequence 1,1,3.&lt;/p&gt;
&lt;p&gt;I now leave as an exercise for the reader to show that this operation preserves the invariant above.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; i j bs (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; j' k cs zs))
  | j == j' = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; k (next j k) (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a bs cs) zs
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a rs = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a) rs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I cheat a bit, and use the (1,1) digit twice to save a little work, rather than start with (1,-1).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exercise:&lt;/strong&gt; Why does this work?&lt;/p&gt;
&lt;p&gt;This yields the following progression:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can compute the size of the random access list in log time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exercise:&lt;/strong&gt; Why?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ i _ &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = i + size &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now write a routine that indexes into a given Leonardo random access list in log time:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(!) :: &lt;span class=&quot;hljs-type&quot;&gt;Leonardo&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; a
&lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; ! i = undefined
&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; j k a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ! i
  | i &amp;lt; k     = go i (prev j k) j a
  | otherwise = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ! (i - k)
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; _ _ (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; a) = a
    go &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; _ _ (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a _ _) = a
    go i j k (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ l r)
      | i &amp;lt;= j    = go (i-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)  (prev2 j k) (prev j k) l
      | otherwise = go (i-j-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (prev j k) j r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like I showed with skew-binary random access lists for &lt;a href=&quot;https://comonad.com/reader/2015/online-lca/&quot;&gt;on-line lowest common ancestor search&lt;/a&gt;, you should be able to compute how to &lt;code&gt;drop n&lt;/code&gt; elements from a list in &lt;code&gt;O(log n)&lt;/code&gt; time. This should work as a drop-in replacement for skew-binary random access lists in that algorithm as well.&lt;/p&gt;
&lt;p&gt;The spine is actually quite a bit shorter than the spine of a skew-binary random access list in terms of constant factors in exchange for the trees being correspondingly taller. (Dijkstra ended EWD797 on this note.)&lt;/p&gt;
&lt;p&gt;Consequently, this pretty much works as a drop in replacement for a skew-binary random access list.&lt;/p&gt;
&lt;p&gt;The code is available all together in a short &lt;a href=&quot;https://gist.github.com/ekmett/036e28ff705cb27e9de6&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;simplifying-the-spine&quot;&gt;Simplifying the Spine&lt;/h2&gt;
&lt;p&gt;It is somewhat ugly that we store two coefficients in each node in the spine. There is a scheme by Dijkstra that manages to track everything
with a simple bit vector for which Leonardo numbers are present in the tree and a single pair of adjacent Leonardo numbers for where to start counting. He uses this in smoothsort to argue for it really being a fully in-place algorithm. On the other hand, it'd considerably complicate &lt;code&gt;cons&lt;/code&gt;, above.&lt;/p&gt;
&lt;p&gt;I leave this as an exercise for the reader as well.&lt;/p&gt;
&lt;h2 id=&quot;why-care&quot;&gt;Why Care?&lt;/h2&gt;
&lt;p&gt;Gerth Stølting Brodal pointed out &lt;a href=&quot;http://dl.acm.org/citation.cfm?id=1276254&quot;&gt;in a paper with Gabriel Moruz&lt;/a&gt; that balancing your tree wasn't actually optimal on real hardware. We have branch predictions, cache effects, etc. Consequently, the costs of going left vs. going right aren't the same!&lt;/p&gt;
&lt;p&gt;(He also has &lt;a href=&quot;http://www.cs.au.dk/~gerth/slides/cphstl06.pdf&quot;&gt;slides available&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;In particular, he showed empirically a bias to one side can speed things up considerably due to these effects. Something like 30% or so was the optimal balance, gaining up to 15% performance over a &quot;real&quot; balanced binary tree.&lt;/p&gt;
&lt;p&gt;The ratio between consecutive Leonardo numbers approaches to the golden ratio φ and &lt;code&gt;1/(1+φ) ~ 38%&lt;/code&gt; at least gets us in that ballpark.&lt;/p&gt;
&lt;p&gt;Is there a nice, cheap, recurrence that gets us closer and retains the nice property that &lt;code&gt;cons&lt;/code&gt; is also &lt;em&gt;O(1)&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;April 27, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/fibonacci-leonardo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Making Dependent Types Practical</title><link>https://comonad.com/reader/talks/youtube-_2jrmgO_Gq0/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-_2jrmgO_Gq0/</guid><pubDate>Wed, 15 Apr 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Chris Casinghino · 15 April 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;_2jrmgO_Gq0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=_2jrmgO_Gq0&quot;&gt;Watch on YouTube&lt;/a&gt; · 61 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Aᴘʀɪʟ 15, 2015 @ Bᴏsᴛᴏɴ Hᴀsᴋᴇʟʟ: &lt;a href=&quot;http://www.meetup.com/Boston-Haskell/events/219653486/&quot;&gt;http://www.meetup.com/Boston-Haskell/events/219653486/&lt;/a&gt;&lt;br&gt;
Sʟɪᴅᴇs: &lt;a href=&quot;http://tyconmismatch.com/bh_talk.pdf&quot;&gt;http://tyconmismatch.com/bh_talk.pdf&lt;/a&gt;&lt;br&gt;
&quot;The last decade has seen many success stories for verified programming with dependent types, including the CompCert verified C compiler, verified libraries for concurrency and security, and machine-checked proofs of results like the four color theorem and the Feit-Thompson theorem.  Despite these successes, dependently typed languages are rarely used for day-to-day programming tasks.  In this talk, I’ll describe several limitations of modern dependently-typed languages that are holding them back from wider adoption for practical programming tasks.  I’ll explain the historical and mathematical reasons for these limitations, and describe how we attempted to relax them in the design of the Zombie research language.&quot;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://tyconmismatch.com/bh_talk.pdf&quot;&gt;slides&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-_2jrmgO_Gq0/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Reflex: Practical Functional Reactive Programming</title><link>https://comonad.com/reader/talks/youtube-dOy7zIk3IUI/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-dOy7zIk3IUI/</guid><pubDate>Wed, 15 Apr 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Ryan Trinkle · 15 April 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;dOy7zIk3IUI&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=dOy7zIk3IUI&quot;&gt;Watch on YouTube&lt;/a&gt; · 66 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Aᴘʀɪʟ 15, 2015 @ Bᴏsᴛᴏɴ Hᴀsᴋᴇʟʟ: &lt;a href=&quot;http://www.meetup.com/Boston-Haskell/events/219653486/&quot;&gt;http://www.meetup.com/Boston-Haskell/events/219653486/&lt;/a&gt;&lt;br&gt;
Sʟɪᴅᴇs: &lt;a href=&quot;https://obsidian.systems/reflex-nyhug/&quot;&gt;https://obsidian.systems/reflex-nyhug/&lt;/a&gt;&lt;br&gt;
&quot;Ryan Trinkle presents his new library, Reflex, a deterministic, efficient, higher-order Functional Reactive Programming system. FRP is a radically new paradigm for writing interactive software: Instead of writing event loops or callbacks, programmers compose interactive applications using ordinary pure functional programming methods. The unique design of Reflex gives it the power and flexibility necessary to handle complex large-scale applications. Reflex can be compiled to binary using GHC or JavaScript using GHCJS.&quot;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://obsidian.systems/reflex-nyhug/&quot;&gt;slides&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-dOy7zIk3IUI/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Framing the Discussion with EDSLs</title><link>https://comonad.com/reader/talks/youtube-_KioQRICpmo/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-_KioQRICpmo/</guid><pubDate>Wed, 25 Mar 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Anthony Cowley · 25 March 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;_KioQRICpmo&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=_KioQRICpmo&quot;&gt;Watch on YouTube&lt;/a&gt; · 101 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Anthony Cowley's Talk for the Boston Haskell Meetup. March 25&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://raw.githubusercontent.com/acowley/BostonHaskell2015/master/edsl.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/acowley/BostonHaskell2015/blob/master/Lang.hs&quot;&gt;source code&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-_KioQRICpmo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Free Monoids in Haskell</title><link>https://comonad.com/reader/2015/free-monoids-in-haskell/</link><guid isPermaLink="false">https://comonad.com/reader/2015/free-monoids-in-haskell/</guid><pubDate>Sat, 21 Feb 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 21 February 2015&lt;/p&gt;&lt;p&gt;It is often stated that &lt;code&gt;Foldable&lt;/code&gt; is effectively the &lt;code&gt;toList&lt;/code&gt; class. However, this turns out to be wrong. The real fundamental member of &lt;code&gt;Foldable&lt;/code&gt; is &lt;code&gt;foldMap&lt;/code&gt; (which should look suspiciously like &lt;code&gt;traverse&lt;/code&gt;, incidentally). To understand exactly why this is, it helps to understand another surprising fact: lists are not free monoids in Haskell.&lt;/p&gt;
&lt;p&gt;This latter fact can be seen relatively easily by considering another list-like type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;SL&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;SL&lt;/span&gt; a :&amp;gt; a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;SL&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt;
  mappend ys &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt; = ys
  mappend ys (xs :&amp;gt; x) = (mappend ys xs) :&amp;gt; x

&lt;span class=&quot;hljs-title&quot;&gt;single&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;SL&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;single&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt; :&amp;gt; x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, we have a type &lt;code&gt;SL a&lt;/code&gt; of snoc lists, which are a monoid, and a function that embeds &lt;code&gt;a&lt;/code&gt; into &lt;code&gt;SL a&lt;/code&gt;. If (ordinary) lists were the free monoid, there would be a unique monoid homomorphism from lists to snoc lists. Such a homomorphism (call it &lt;code&gt;h&lt;/code&gt;) would have the following properties:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [] = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; (xs &amp;lt;&amp;gt; ys) = h xs &amp;lt;&amp;gt; h ys
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [x] = single x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And in fact, this (together with some general facts about Haskell functions) should be enough to define &lt;code&gt;h&lt;/code&gt; for our purposes (or any purposes, really). So, let's consider its behavior on two values:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] = single &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] = h ([&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] &amp;lt;&amp;gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..]) &lt;span class=&quot;hljs-comment&quot;&gt;-- [1,1..] is an infinite list of 1s&lt;/span&gt;
    = h [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] &amp;lt;&amp;gt; h [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This second equation can tell us what the value of &lt;code&gt;h&lt;/code&gt; is at this infinite value, since we can consider it the definition of a possibly infinite value:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = h [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] &amp;lt;&amp;gt; x = fix (single &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;gt;)
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;(single 1 &amp;lt;&amp;gt;)&lt;/code&gt; is a strict function, so the fixed point theorem tells us that &lt;code&gt;x = ⊥&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is a problem, though. Considering some additional equations:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] &amp;lt;&amp;gt; [n] = [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] &lt;span class=&quot;hljs-comment&quot;&gt;-- true for all n&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] = ⊥
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; ([&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] &amp;lt;&amp;gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]) = h [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..] &amp;lt;&amp;gt; h [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
       = ⊥ &amp;lt;&amp;gt; single &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
       = ⊥ :&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
       ≠ ⊥
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, our requirements for &lt;code&gt;h&lt;/code&gt; are contradictory, and no such homomorphism can exist.&lt;/p&gt;
&lt;p&gt;The issue is that Haskell types are domains. They contain these extra partially defined values and infinite values. The monoid structure on (cons) lists has infinite lists absorbing all right-hand sides, while the snoc lists are just the opposite.&lt;/p&gt;
&lt;p&gt;This also means that finite lists (or any method of implementing finite sequences) are not free monoids in Haskell. They, as domains, still contain the additional bottom element, and it absorbs all other elements, which is incorrect behavior for the free monoid:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;pure&lt;/span&gt; x &amp;lt;&amp;gt; ⊥ = ⊥
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; ⊥ = ⊥
&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; (pure x &amp;lt;&amp;gt; ⊥) = [x] &amp;lt;&amp;gt; h ⊥
    = [x] ++ ⊥
    = x:⊥
    ≠ ⊥
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, what is the free monoid? In a sense, it can't be written down at all in Haskell, because we cannot enforce value-level equations, and because we don't have quotients. But, if conventions are good enough, there is a way. First, suppose we have a free monoid type &lt;code&gt;FM a&lt;/code&gt;. Then for any other monoid &lt;code&gt;m&lt;/code&gt; and embedding &lt;code&gt;a -&amp;gt; m&lt;/code&gt;, there must be a monoid homomorphism from &lt;code&gt;FM a&lt;/code&gt; to &lt;code&gt;m&lt;/code&gt;. We can model this as a Haskell type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; a m. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; (a -&amp;gt; m) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; a -&amp;gt; m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where we consider the &lt;code&gt;Monoid m&lt;/code&gt; constraint to be enforcing that &lt;code&gt;m&lt;/code&gt; actually has valid monoid structure. Now, a trick is to recognize that this sort of universal property can be used to &lt;em&gt;define&lt;/em&gt; types in Haskell (or, GHC at least), due to polymorphic types being first class; we just rearrange the arguments and quantifiers, and take &lt;code&gt;FM a&lt;/code&gt; to be the polymorphic type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unFM&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Types defined like this are automatically universal in the right sense. &lt;a href=&quot;https://comonad.com/reader/2015/free-monoids-in-haskell/#footnote-1&quot;&gt;[1]&lt;/a&gt; The only thing we have to check is that &lt;code&gt;FM a&lt;/code&gt; is actually a monoid over &lt;code&gt;a&lt;/code&gt;. But that turns out to be easily witnessed:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;embed&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;embed&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \k -&amp;gt; k x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \_ -&amp;gt; mempty
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; e1) (&lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; e2) = &lt;span class=&quot;hljs-type&quot;&gt;FM&lt;/span&gt; $ \k -&amp;gt; e1 k &amp;lt;&amp;gt; e2 k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Demonstrating that the above is a proper monoid delegates to instances of &lt;code&gt;Monoid&lt;/code&gt; being proper monoids. So as long as we trust that convention, we have a free monoid.&lt;/p&gt;
&lt;p&gt;However, one might wonder what a free monoid would look like as something closer to a traditional data type. To construct that, first ignore the required equations, and consider only the generators; we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FMG&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Single&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;FMG&lt;/span&gt; a :&amp;lt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FMG&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the proper &lt;code&gt;FM a&lt;/code&gt; is the quotient of this by the equations:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; :&amp;lt;&amp;gt; x = x = x :&amp;lt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; :&amp;lt;&amp;gt; (y :&amp;lt;&amp;gt; z) = (x :&amp;lt;&amp;gt; y) :&amp;lt;&amp;gt; z
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One way of mimicking this in Haskell is to hide the implementation in a module, and only allow elimination into &lt;code&gt;Monoid&lt;/code&gt;s (again, using the convention that &lt;code&gt;Monoid&lt;/code&gt; ensures actual monoid structure) using the function:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unFMG&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a m. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FMG&lt;/span&gt; a -&amp;gt; (a -&amp;gt; m) -&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;unFMG&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; _ = mempty
&lt;span class=&quot;hljs-title&quot;&gt;unFMG&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Single&lt;/span&gt; x) k = k x
&lt;span class=&quot;hljs-title&quot;&gt;unFMG&lt;/span&gt; (x :&amp;lt;&amp;gt; y) k = unFMG x k &amp;lt;&amp;gt; unFMG y k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is actually how quotients can be thought of in richer languages; the quotient does not eliminate any of the generated structure internally, it just restricts the way in which the values can be consumed. Those richer languages just allow us to prove equations, and enforce properties by proof obligations, rather than conventions and structure hiding. Also, one should note that the above should look pretty similar to our encoding of &lt;code&gt;FM a&lt;/code&gt; using universal quantification earlier.&lt;/p&gt;
&lt;p&gt;Now, one might look at the above and have some objections. For one, we'd normally think that the quotient of the above type is just &lt;code&gt;[a]&lt;/code&gt;. Second, it seems like the type is revealing something about the associativity of the operations, because defining recursive values via left nesting is different from right nesting, and this difference is observable by extracting into different monoids. But aren't monoids supposed to remove associativity as a concern? For instance:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ones1&lt;/span&gt; = embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;gt; ones1
&lt;span class=&quot;hljs-title&quot;&gt;ones2&lt;/span&gt; = ones2 &amp;lt;&amp;gt; embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Shouldn't we be able to prove these are the same, becuase of an argument like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ones1&lt;/span&gt; = embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;gt; (embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;gt; ...)
      ... reassociate ...
      = (... &amp;lt;&amp;gt; embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &amp;lt;&amp;gt; embed &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
      = ones2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The answer is that the equation we have only specifies the behavior of associating three values:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; &amp;lt;&amp;gt; (y &amp;lt;&amp;gt; z) = (x &amp;lt;&amp;gt; y) &amp;lt;&amp;gt; z
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And while this is sufficient to nail down the behavior of &lt;em&gt;finite&lt;/em&gt; values, and &lt;em&gt;finitary&lt;/em&gt; reassociating, it does not tell us that &lt;em&gt;infinitary&lt;/em&gt; reassociating yields the same value back. And the &quot;... reassociate ...&quot; step in the argument above was decidedly infinitary. And while the rules tell us that we can peel any finite number of copies of &lt;code&gt;embed 1&lt;/code&gt; to the front of &lt;code&gt;ones1&lt;/code&gt; or the end of &lt;code&gt;ones2&lt;/code&gt;, it does not tell us that &lt;code&gt;ones1 = ones2&lt;/code&gt;. And in fact it is vital for &lt;code&gt;FM a&lt;/code&gt; to have distinct values for these two things; it is what makes it the free monoid when we're dealing with domains of lazy values.&lt;/p&gt;
&lt;p&gt;Finally, we can come back to &lt;code&gt;Foldable&lt;/code&gt;. If we look at &lt;code&gt;foldMap&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foldMap&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m) =&amp;gt; (a -&amp;gt; m) -&amp;gt; f a -&amp;gt; m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can rearrange things a bit, and get the type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; f a -&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; m. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; m =&amp;gt; (a -&amp;gt; m) -&amp;gt; m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And thus, the most fundamental operation of &lt;code&gt;Foldable&lt;/code&gt; is not &lt;code&gt;toList&lt;/code&gt;, but &lt;code&gt;toFreeMonoid&lt;/code&gt;, and lists are not free monoids in Haskell.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;footnote-1&quot;&gt;&lt;/span&gt;[1]: What we are doing here is noting that (co)limits are objects that internalize natural transformations, but the natural transformations expressible by quantification in GHC are already automatically internalized using quantifiers. However, one has to be careful that the quantifiers are actually enforcing the relevant naturality conditions. In many simple cases they are.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/free-monoids-in-haskell/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Enigmatic Haskell, Haskellish Enigma</title><link>https://comonad.com/reader/talks/youtube-9-u2n4GgcVw/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-9-u2n4GgcVw/</guid><pubDate>Wed, 18 Feb 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Rishiyur S. Nikhil · 18 February 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;9-u2n4GgcVw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=9-u2n4GgcVw&quot;&gt;Watch on YouTube&lt;/a&gt; · 59 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Boston Haskell, February 18, 2015&lt;br&gt;
Nikhil builds an Enigma machine. First in Cryptol, then in hardware by way of Haskell.&lt;br&gt;
Slides and code available here:  &lt;a href=&quot;https://github.com/rsnikhil/Enigma_Cryptol_Bluespec_BSV.git&quot;&gt;https://github.com/rsnikhil/Enigma_Cryptol_Bluespec_BSV.git&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/rsnikhil/Enigma_Cryptol_Bluespec_BSV&quot;&gt;slides and code&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-9-u2n4GgcVw/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Pure Type Systems</title><link>https://comonad.com/reader/talks/youtube-ZGqKsalJi4s/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-ZGqKsalJi4s/</guid><pubDate>Wed, 18 Feb 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Cody Roux · 18 February 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;ZGqKsalJi4s&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZGqKsalJi4s&quot;&gt;Watch on YouTube&lt;/a&gt; · 77 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Cody Roux's talk for the Boston Haskell Meetup - February 18, 2015&lt;br&gt;
Slides: &lt;a href=&quot;http://www.slideshare.net/imalsogreg/cody-roux-pure-type-systems-boston-haskell-meetup&quot;&gt;http://www.slideshare.net/imalsogreg/cody-roux-pure-type-systems-boston-haskell-meetup&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/imalsogreg/cody-roux-pure-type-systems-boston-haskell-meetup&quot;&gt;slides&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-ZGqKsalJi4s/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The free theorem for fmap</title><link>https://comonad.com/reader/2015/snippets-fmap/</link><guid isPermaLink="false">https://comonad.com/reader/2015/snippets-fmap/</guid><pubDate>Mon, 16 Feb 2015 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 16 February 2015&lt;/p&gt;&lt;p&gt;When we write down the definition of &lt;code&gt;Functor&lt;/code&gt; we carefully state two laws:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;fmap id = id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fmap f . fmap g = fmap (f . g)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are pretty well known in the Haskell community.&lt;/p&gt;
&lt;p&gt;What is less well known is that the second actually follows from the first and parametricity, so you only need to sit down and prove &lt;em&gt;one&lt;/em&gt; &lt;code&gt;Functor&lt;/code&gt; law when you go to supply a &lt;code&gt;Functor&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;This is a “folklore” result, which I've used in conversation many times before, but it &lt;a href=&quot;https://twitter.com/BartoszMilewski/status/566204998015787008&quot;&gt;continues to surprise&lt;/a&gt; folks, so I decided to write up a slow, step by step proof of this result as it is a fun little exercise in equational reasoning.&lt;/p&gt;
&lt;p&gt;To prove this we're going to need the &lt;a href=&quot;http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf&quot;&gt;free theorem&lt;/a&gt; for &lt;code&gt;fmap&lt;/code&gt; and a few lemmas.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;###Free Theorem:&lt;/p&gt;
&lt;p&gt;The free theorem for &lt;code&gt;fmap :: (a -&amp;gt; b) -&amp;gt; F a -&amp;gt; F b&lt;/code&gt; is that given functions &lt;code&gt;f&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, and &lt;code&gt;h&lt;/code&gt; such that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; . h = k . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;$map g . fmap h = fmap k . $map f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;$map&lt;/code&gt; is the &quot;natural map&quot; for the type constructor &lt;code&gt;F&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;###Proof:&lt;/p&gt;
&lt;p&gt;This is a free theorem, so it holds for &lt;em&gt;any&lt;/em&gt; function with the same type signature as
&lt;code&gt;fmap&lt;/code&gt;, regardless of implementation.&lt;/p&gt;
&lt;p&gt;You can obtain this theorem employing Philip Wadler's &lt;a href=&quot;http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf&quot;&gt;“Theorems for Free”&lt;/a&gt; laboriously by hand as is done by Bartosz in the comments below, but we can also obtain this result just by asking &lt;code&gt;lambdabot&lt;/code&gt; to do it for us on IRC.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;edwardk&amp;gt; @free fmap :: (a -&amp;gt; b) -&amp;gt; (F a -&amp;gt; F b)
&amp;lt;lambdabot&amp;gt; g . h = k . f =&amp;gt; $map_F g . fmap h = fmap k . $map_F f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thanks, &lt;code&gt;lambdabot&lt;/code&gt;!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The natural map has the properties we're looking for, so what we need to do is use the above theorem to prove &lt;code&gt;fmap f = $map f&lt;/code&gt;, and borrow them.&lt;/p&gt;
&lt;p&gt;Note: There are some caveats about precisely when such a natural map exists in the comments below, but in any case where &lt;code&gt;fmap&lt;/code&gt; can be given with &lt;code&gt;fmap id = id&lt;/code&gt;, it can also exist with this variance.&lt;/p&gt;
&lt;p&gt;To do that we start with&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;###Lemma 1:&lt;/p&gt;
&lt;p&gt;Given &lt;code&gt;fmap id = id&lt;/code&gt;, then&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f = $map f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;###Proof:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by $map id = id -}&lt;/span&gt;
$map id . fmap f
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by free theorem, using g = k = id, h = f -}&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; id . $map f
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by fmap id = id -}&lt;/span&gt;
$map f
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we know that &lt;code&gt;fmap f = $map f&lt;/code&gt; pointwise, and if we assume functional extensionality, we can even show &lt;code&gt;fmap = $map&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lemma 1&lt;/strong&gt; is sufficient to show that any two definitions &lt;code&gt;fmap1&lt;/code&gt; and &lt;code&gt;fmap2&lt;/code&gt; for &lt;code&gt;fmap&lt;/code&gt; that each satisfy &lt;code&gt;fmap id = id&lt;/code&gt;, are equivalent up to functional extensionality, as of course &lt;code&gt;fmap1 f = $map f = fmap2 f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Therefore the observable behavior of &lt;code&gt;fmap&lt;/code&gt; is uniquely determined.&lt;/p&gt;
&lt;p&gt;Next we'll, need another precondition:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;###Lemma 2:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; . g = id . (f . g)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;###Proof:&lt;/p&gt;
&lt;p&gt;Naively, &lt;code&gt;id&lt;/code&gt; is the unit for &lt;code&gt;(.)&lt;/code&gt;. In reality it results in it eta-expanded.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we're finally ready to proceed to the real proof:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;###Theorem:&lt;/p&gt;
&lt;p&gt;Given &lt;code&gt;fmap id = id&lt;/code&gt;, we can show that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f . fmap g = fmap (f . g)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;###Proof:&lt;/p&gt;
&lt;p&gt;We can read this off of the properties of the free theorem several ways.&lt;/p&gt;
&lt;p&gt;The easiest one which does not use the same shaped property on &lt;code&gt;$map&lt;/code&gt; is to just play with &lt;code&gt;$map id = id&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f . fmap g
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by lemma 1, fmap f = $map f -}&lt;/span&gt;
$map f . fmap g
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by the free theorem for fmap using lemma 2 for the precondition -}&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; id . $map (f . g)
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by fmap id = id -}&lt;/span&gt;
$map (f . g)
= &lt;span class=&quot;hljs-comment&quot;&gt;{- by fmap _ = $map _ -}&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; (f . g)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;(We could have also employed the fact that &lt;code&gt;$map f . $map g = $map (f . g)&lt;/code&gt; more directly.)&lt;/p&gt;
&lt;p&gt;There is definitely room to improve this proof. It would be more satisfying to start with
two definitions of &lt;code&gt;fmap&lt;/code&gt; such that they both satisfy &lt;code&gt;fmap_1 id = id&lt;/code&gt; and &lt;code&gt;fmap_2 id = id&lt;/code&gt;, and show that they must be equivalent up to functional extensionality, rather than appeal to the existence of a &quot;natural map&quot;, which is a bit hand wavy.  Russell O'Connor &lt;a href=&quot;http://thread.gmane.org/gmane.comp.lang.haskell.libraries/15382/focus=15384&quot;&gt;took a similar approach&lt;/a&gt; to concisely show that &lt;code&gt;fmap&lt;/code&gt; is uniquely determined, if it exists, on the &lt;code&gt;libraries&lt;/code&gt; mailing list.&lt;/p&gt;
&lt;p&gt;But there you have it. Next time you go to write a &lt;code&gt;Functor&lt;/code&gt;, you can rest assured that you only need to prove &lt;code&gt;fmap id = id&lt;/code&gt;, and you can get the other result for free!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;February 15, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/snippets-fmap/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Type Classes vs. the World</title><link>https://comonad.com/reader/talks/youtube-hIZxTQP1ifo/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-hIZxTQP1ifo/</guid><pubDate>Wed, 21 Jan 2015 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 21 January 2015&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;hIZxTQP1ifo&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hIZxTQP1ifo&quot;&gt;Watch on YouTube&lt;/a&gt; · 102 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Boston Haskell Meetup - January 21, 2015&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-hIZxTQP1ifo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Fast Circular Substitution</title><link>https://comonad.com/reader/2014/fast-circular-substitution/</link><guid isPermaLink="false">https://comonad.com/reader/2014/fast-circular-substitution/</guid><pubDate>Tue, 30 Dec 2014 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 December 2014&lt;/p&gt;&lt;span id=&quot;more-956&quot;&gt;&lt;/span&gt;&lt;p&gt;Emil Axelsson and Koen Claessen wrote a functional pearl last year about &lt;a href=&quot;http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf&quot;&gt;Using Circular Programs for Higher-Order Syntax&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;About 6 months ago I had an opportunity to play with this approach in earnest, and realized we can speed it up a great deal. This has kept coming up in conversation ever since, so I've decided to write up an article here.&lt;/p&gt;
&lt;p&gt;In my &lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;bound&lt;/a&gt; library I exploit the fact that monads are about substitution to make a monad transformer that manages substitution for me.&lt;/p&gt;
&lt;p&gt;Here I'm going to take a more coupled approach.&lt;/p&gt;
&lt;p&gt;To have a type system with enough complexity to be worth examining, I'll adapt Dan Doel's &lt;a href=&quot;http://hub.darcs.net/dolio/upts&quot;&gt;UPTS&lt;/a&gt;, which is a pure type system with universe polymorphism. I won't finish the implementation here, but from where we get it should be obvious how to finish the job.&lt;/p&gt;
&lt;p&gt;Unlike Axelsson and Claessen I'm not going to bother to abstract over my name representation.&lt;/p&gt;
&lt;p&gt;To avoid losing the original name from the source, we'll just track names as strings with an integer counting the number of times it has been 'primed'. The name is purely for expository purposes, the real variable identifier is the number. We'll follow the Axelsson and Claessen convention of having the identifier assigned to each binder be larger than any one bound inside of it. If you don't need he original source names you can cull them from the representation, but they can be useful if you are representing a syntax tree for something you parsed and/or that you plan to pretty print later.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;hint&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;hint&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; n _) = n

&lt;span class=&quot;hljs-title&quot;&gt;nameId&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;nameId&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; _ i) = i
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (==) = (==) `on` nameId
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare = compare `on` nameId

&lt;span class=&quot;hljs-title&quot;&gt;prime&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;prime&lt;/span&gt; n i = &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; n (i + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what is the language I want to work with?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Level&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Level&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;LevelLiteral&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Level&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Omega&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Typeable&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a :+ &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Level&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Max&lt;/span&gt;  [&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a]
  | &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt;   &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt;    &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Sigma&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Typeable&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is perhaps a bit paranoid about remaining strict, but it seemed like a good idea at the time.&lt;/p&gt;
&lt;p&gt;We can define capture avoiding substitution on terms:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;subst&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;subst&lt;/span&gt; a x y = y &amp;gt;&amp;gt;= \a' -&amp;gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; a == a'
    &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; x
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; return a'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we finally need to implement Axelsson and Claessen's circular programming trick. Here we'll abstract over terms that allow us to find the highest bound value within them:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bindable&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bound :: t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and instantiate it for our &lt;code&gt;Term&lt;/code&gt; type&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bindable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bound &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;{}        = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  bound &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt;{}       = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- intentional!&lt;/span&gt;
  bound &lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt;{}    = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  bound (a :+ _)      = bound a
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Max&lt;/span&gt; xs)      = foldr (\a r -&amp;gt; bound a `max` r) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; xs
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; t)      = bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b t _)   = nameId b `max` bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt; b t _)    = nameId b `max` bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Sigma&lt;/span&gt; b t _) = nameId b `max` bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y)     = bound x `max`  bound y
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; t)       = bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; t)       = bound t
  bound (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; t x y)  = bound t `max` bound x `max` bound y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As in the original pearl we avoid traversing into the body of the binders, hence the _'s in the code above.&lt;/p&gt;
&lt;p&gt;Now we can abstract over the pattern used to create a binder in the functional pearl, since we have multiple binder types in this syntax tree, and the code would get repetitive.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;binder&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bindable&lt;/span&gt; t =&amp;gt;
  (&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; t) -&amp;gt;
  (&lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; t -&amp;gt; r) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; (t -&amp;gt; t) -&amp;gt; r
&lt;span class=&quot;hljs-title&quot;&gt;binder&lt;/span&gt; bd c n e = c b body &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  body = e (bd b)
  b = prime n (bound body)

&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt;, pi, sigma :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; s t   = binder &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; (`&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt;` t) s
&lt;span class=&quot;hljs-title&quot;&gt;pi&lt;/span&gt; s t    = binder &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; (`&lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt;` t) s
&lt;span class=&quot;hljs-title&quot;&gt;sigma&lt;/span&gt; s t = binder &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; (`&lt;span class=&quot;hljs-type&quot;&gt;Sigma&lt;/span&gt;` t) s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We may not always want to give names to the variables we capture, so let's define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam_&lt;/span&gt;, pi_, sigma_ :: &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam_&lt;/span&gt;   = lam &lt;span class=&quot;hljs-string&quot;&gt;&quot;_&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;pi_&lt;/span&gt;    = pi &lt;span class=&quot;hljs-string&quot;&gt;&quot;_&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sigma_&lt;/span&gt; = sigma &lt;span class=&quot;hljs-string&quot;&gt;&quot;_&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, here's the interesting part. The problem with Axelsson and Claessen's original trick is that every substitution is being handled separately. This means that if you were to write a monad for doing substitution with it, it'd actually be quite slow. You have to walk the syntax tree over and over and over.&lt;/p&gt;
&lt;p&gt;We can fuse these together by making a single pass:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Name&lt;/span&gt; -&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; t
&lt;span class=&quot;hljs-title&quot;&gt;instantiate&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.insert . nameId

&lt;span class=&quot;hljs-title&quot;&gt;rebind&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; b
&lt;span class=&quot;hljs-title&quot;&gt;rebind&lt;/span&gt; env xs0 f = go xs0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = \&lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; a       -&amp;gt; f a
    &lt;span class=&quot;hljs-type&quot;&gt;Bound&lt;/span&gt; b      -&amp;gt; env &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.! nameId b
    &lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt; c   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constant&lt;/span&gt; c
    m :+ n       -&amp;gt; go m :+ n
    &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; t       -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Type&lt;/span&gt; (go t)
    &lt;span class=&quot;hljs-type&quot;&gt;Max&lt;/span&gt; xs       -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Max&lt;/span&gt; (fmap go xs)
    &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b t e    -&amp;gt; lam   (hint b) (go t) $ \v -&amp;gt;
      rebind (instantiate b v env) e f
    &lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt; b t e     -&amp;gt; pi    (hint b) (go t) $ \v -&amp;gt;
      rebind (instantiate b v env) e f
    &lt;span class=&quot;hljs-type&quot;&gt;Sigma&lt;/span&gt; b t e  -&amp;gt; sigma (hint b) (go t) $ \v -&amp;gt;
      rebind (instantiate b v env) e f
    &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y      -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (go x) (go y)
    &lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; x        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; (go x)
    &lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; x        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; (go x)
    &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; t x y   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (go t) (go x) (go y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the &lt;code&gt;Lam&lt;/code&gt;, &lt;code&gt;Pi&lt;/code&gt; and &lt;code&gt;Sigma&lt;/code&gt; cases just extend the current environment.&lt;/p&gt;
&lt;p&gt;With that now we can upgrade the pearl's encoding to allow for an actual Monad in the same sense as &lt;code&gt;bound&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;
  (&amp;lt; *&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;
  (&amp;gt;&amp;gt;=) = rebind &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.empty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To show that we can work with this syntax tree representation, let's write an evaluator from it to weak head normal form:&lt;/p&gt;
&lt;p&gt;First we'll need some helpers:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;apply&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;apply&lt;/span&gt; = foldl &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a) -&amp;gt;
  [&lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; env stk     (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f x)
  = rwhnf env (rebind env x &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;:stk) f
&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; env (x:stk) (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; b _ e)
  = rwhnf (instantiate b x env) stk e
&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; env stk (&lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; e)
  = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; rwhnf env [] e &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; _ e' _ -&amp;gt; rwhnf env stk e'
  e'          -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fst&lt;/span&gt; e'
&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; env stk (&lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; e)
  = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; rwhnf env [] e &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; _ _ e' -&amp;gt; rwhnf env stk e'
  e'          -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Snd&lt;/span&gt; e'
&lt;span class=&quot;hljs-title&quot;&gt;rwhnf&lt;/span&gt; env stk e
  = apply (rebind env e &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;) stk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can start off the &lt;code&gt;whnf&lt;/code&gt; by calling our helper with an initial starting environment:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;whnf&lt;/span&gt; = rwhnf &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.empty []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what have we given up? Well, &lt;code&gt;bound&lt;/code&gt; automatically lets you compare terms for alpha equivalence by quotienting out the placement of &quot;F&quot; terms in the syntax tree. Here we have a problem in that the identifiers we get assigned aren't necessarily canonical.&lt;/p&gt;
&lt;p&gt;But we can get the same identifiers out by just using the monad above:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;alphaEq&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;alphaEq&lt;/span&gt; = (==) `on` liftM id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It makes me a bit uncomfortable that our monad is only up to alpha equivalence and that &lt;code&gt;liftM&lt;/code&gt; swaps out the identifiers used throughout the entire syntax tree, and we've also lost the ironclad protection against exotic terms.&lt;/p&gt;
&lt;p&gt;But overall, this is a much faster version of Axelsson and Claessen's trick and it can be used as a drop-in replacement for something like &lt;code&gt;bound&lt;/code&gt; in many cases, and unlike bound, it lets you use HOAS-style syntax for constructing &lt;code&gt;lam&lt;/code&gt;, &lt;code&gt;pi&lt;/code&gt; and &lt;code&gt;sigma&lt;/code&gt; terms.&lt;/p&gt;
&lt;p&gt;With pattern synonyms you can prevent the user from doing bad things as well. Once 7.10 ships you'd be able to use a bidirectional pattern synonym for &lt;code&gt;Pi&lt;/code&gt;, &lt;code&gt;Sigma&lt;/code&gt; and &lt;code&gt;Lam&lt;/code&gt; to hide the real constructors behind. I'm not yet sure of the &quot;best practices&quot; in this area.&lt;/p&gt;
&lt;p&gt;Here's the code all in one place:&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://comonad.com/assets/imported/ea8840c3fab3-Circular.hs&quot;&gt;Download Circular.hs&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;Happy Holidays,&lt;br&gt;
-Edward&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/fast-circular-substitution/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Lightning talks - Dec. 2014</title><link>https://comonad.com/reader/talks/youtube-yFXzuCFeRGM/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-yFXzuCFeRGM/</guid><category>Talk</category><description>&lt;p&gt;Darius Jahandarie, Elliot Stern, William Blair, Kenneth Foner, Tom Titchener, Edward Kmett · December 2014 · day unknown&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;yFXzuCFeRGM&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yFXzuCFeRGM&quot;&gt;Watch on YouTube&lt;/a&gt; · 122 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Darius Jahandarie - Rust for Haskellers &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=1s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=1s&lt;/a&gt;&lt;br&gt;
Elliot Stern - Fun with Phantoms  &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=14m58s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=14m58s&lt;/a&gt;&lt;br&gt;
William Blair - Debugging with types in ATS &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=31m30s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=31m30s&lt;/a&gt;&lt;br&gt;
Kenny Foner - Ice, Ice, Data (Freezing mutable data structures with Midas)  &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=50m52s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=50m52s&lt;/a&gt;&lt;br&gt;
Tom Titchener - Building a real simple music generator to parameterize canons. &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=1h12m53s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=1h12m53s&lt;/a&gt;&lt;br&gt;
Edward Kmett - Encapsulation vs. Code Reuse  &lt;a href=&quot;http://youtu.be/yFXzuCFeRGM?t=1h34m55s&quot;&gt;http://youtu.be/yFXzuCFeRGM?t=1h34m55s&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-yFXzuCFeRGM/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Liquid Haskell</title><link>https://comonad.com/reader/talks/youtube-vYh27zz9530/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-vYh27zz9530/</guid><pubDate>Wed, 19 Nov 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Ranjit Jhala · 19 November 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;vYh27zz9530&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=vYh27zz9530&quot;&gt;Watch on YouTube&lt;/a&gt; · 100 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Ranjit's talk on Liquid Haskell, for the Boston Haskell meetup group, November 19 2014&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-vYh27zz9530/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part V: Heaps of Performance</title><link>https://comonad.com/reader/2014/revisiting-matrix-multiplication-part-5/</link><guid isPermaLink="false">https://comonad.com/reader/2014/revisiting-matrix-multiplication-part-5/</guid><pubDate>Sun, 16 Nov 2014 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 16 November 2014&lt;/p&gt;&lt;p&gt;Back in &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/&quot;&gt;part 3&lt;/a&gt; I naïvely plodded ahead with implementing a nice fusion combinator to try to use inside of my matrix multiplication routine.&lt;/p&gt;
&lt;p&gt;It was slow.&lt;/p&gt;
&lt;p&gt;It was slow because I built nested trees of concatenations and merges, and then when pumping it stream fusion was never getting anything that it could unroll into a bigger loop. Moreover, when faced with a tree of merges, the &lt;code&gt;Stream&lt;/code&gt; fusion framework was being forced to keep the associativity by which it was originally constructed, but there was no balance ensuring that tree was any good.&lt;/p&gt;
&lt;p&gt;If you're just joining, you may want to go back and read parts &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/&quot;&gt;1&lt;/a&gt;,&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;2&lt;/a&gt;,&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/&quot;&gt;3&lt;/a&gt;, and &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/&quot;&gt;4&lt;/a&gt;, but like the last two parts, this one mostly stands alone if you ignore the motivation for the trick as a short practicum on how to bootstrap a datastructure and an introduction to pairing heaps and ephemeral steques.&lt;/p&gt;
&lt;h2 id=&quot;work-smarter&quot;&gt;Work Smarter&lt;/h2&gt;
&lt;p&gt;Let's work smarter, not harder, by finding a better algorithm, rather than trying to run a dumb one fast.&lt;/p&gt;
&lt;p&gt;To that end, I need to be able to deal with merging together streams and concatenating streams with a minimum of impact from concatenation on the cost of getting the next element.&lt;/p&gt;
&lt;p&gt;We could of course merge streams by representing them as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Heap_%28data_structure%29&quot;&gt;heap&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pick your favorite heap. Mine today for ease of exposition is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Pairing_Heap&quot;&gt;pairing heap&lt;/a&gt;. It is pretty awful when you want to actually analyze the runtime performance of your algorithm, but it has excellent &lt;a href=&quot;http://en.wikipedia.org/wiki/Amortized_analysis&quot;&gt;amortized&lt;/a&gt; performance in practice and fits the form of what I'm going to put around it.&lt;/p&gt;
&lt;p&gt;I'll deal with only non-empty heaps, as we can move all the reasoning for the empty case into &lt;code&gt;Maybe (Heap a)&lt;/code&gt; and it admits a nicer recursive definition.&lt;/p&gt;
&lt;p&gt;For simplicity, I'll just be using &lt;code&gt;Int&lt;/code&gt; keys rather than &lt;a href=&quot;http://en.wikipedia.org/wiki/Z-order_curve&quot;&gt;Morton-ordered&lt;/a&gt; keys below.&lt;/p&gt;
&lt;p&gt;A pairing heap is a heap built on a &lt;a href=&quot;http://en.wikipedia.org/wiki/Rose_Tree&quot;&gt;rose tree&lt;/a&gt;. That is to say any node in your heap can have any number of children, so long as you satisfy the &lt;a href=&quot;http://xlinux.nist.gov/dads/HTML/heapproperty.html&quot;&gt;heap property&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A pairing heap provides us with a dead simple union for two heaps. Compare them, and then shove the one with the larger starting key one underneath the smaller. That it is.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; x@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) y@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b bs)
  | i &amp;lt;= j    = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a (y:&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b (x:bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can obviously grab the &lt;code&gt;top&lt;/code&gt; element&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a _) = (i, a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can &lt;code&gt;pop&lt;/code&gt; that element off the &lt;code&gt;Heap&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; _ _ [])    = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; _ _ (x:xs) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (merge x xs)

&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x (y:ys) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ys &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  (z:zs) -&amp;gt; mix x y `mix` merge z zs
  []     -&amp;gt; mix x y
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x [] = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The complexity in analyzing the asymptotics of a pairing heap comes from the fact that &lt;code&gt;merge&lt;/code&gt; might have to do a lot of work, but &lt;code&gt;merge&lt;/code&gt; pairs up the heaps before doing it's work to get better balancing. Again, nothing in what I'm writing here cares about the pairing heap parts, other than it is easy to write and similar to the surrounding code we're adding, and it is the most obviously amenable heap to the transformation I'll be applying later.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mix&lt;/code&gt; now handles the behavior I need for merging streams/heaps, but I'm also going to need efficient concatenation. While &lt;code&gt;mix&lt;/code&gt; is &quot;technically correct&quot; for concatenating two heaps that do not overlap in key space, it also isn't terribly good at it.&lt;/p&gt;
&lt;h2 id=&quot;steques&quot;&gt;Steques&lt;/h2&gt;
&lt;p&gt;A &quot;stack-ended queue&quot;, or steque, is what &lt;a href=&quot;http://en.wikipedia.org/wiki/Robert_Tarjan&quot;&gt;Tarjan&lt;/a&gt; calls a structure that permits &lt;code&gt;cons&lt;/code&gt; and &lt;code&gt;snoc&lt;/code&gt; on both ends, but only efficient &lt;code&gt;head&lt;/code&gt;/&lt;code&gt;tail&lt;/code&gt;/&lt;code&gt;uncons&lt;/code&gt; from one side.&lt;/p&gt;
&lt;p&gt;This distinguishes it from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Double-ended_queue&quot;&gt;deque&lt;/a&gt;, which permits efficient &lt;code&gt;init&lt;/code&gt;/&lt;code&gt;tail&lt;/code&gt;/&lt;code&gt;unsnoc&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;The simplest implementation of a steque is&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] [a] &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first list is in order from left to right, and the second list is reversed.&lt;/p&gt;
&lt;p&gt;Note: This isn't the most robust steque or deque in Okasaki's book. Its asymptotics are amortized, not worst case, and they only hold for ephemeral rather than persistent use. However, I only care about that ephemeral use case and so the reduction in book-keeping overhead is more valuable than slower execution to support operations I don't use!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fmap f fs) (fmap f rs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = foldMap f fs `mappend` getDual (foldMap (&lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; . f) rs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use a little bit of &lt;code&gt;lens&lt;/code&gt; to make the &lt;code&gt;Traversable&lt;/code&gt; instance easier, given the
combinator &lt;code&gt;backwards&lt;/code&gt; that can turn a &lt;code&gt;Traversal&lt;/code&gt; around.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &amp;lt;$&amp;gt; traverse f fs &amp;lt;*&amp;gt; backwards traverse f rs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then we could quotient out the irrelevancies of how our elements are distributed between the two lists:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (==) = (==) `on` toList
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare = compare `on` toList
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could even get ambitious and define a bunch of other instances on &lt;code&gt;Steque&lt;/code&gt;, just because we can:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] []
  (&amp;lt;*&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] []
  &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fs &amp;gt;&amp;gt;= toList . f) (bs &amp;gt;&amp;gt;= toListOf (backwards folded) . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;... but we're getting distracted, we really just want to be able to &lt;code&gt;cons&lt;/code&gt;/&lt;code&gt;head&lt;/code&gt;/&lt;code&gt;tail&lt;/code&gt;/&lt;code&gt;uncons&lt;/code&gt;, and &lt;code&gt;snoc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To make this interesting, let us show how to implement these using some lesser understood parts of &lt;code&gt;lens&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt; package provides a common &lt;a href=&quot;https://hackage.haskell.org/packages/archive/lens/3.9.0.2/doc/html/Control-Lens-Cons.html&quot;&gt;&lt;code&gt;Cons&lt;/code&gt;&lt;/a&gt; class for dealing with &lt;code&gt;cons&lt;/code&gt;-like behavior. It is tricky to instantiate correctly, because it is overloaded to permit usecases where you can merely &lt;code&gt;cons&lt;/code&gt; and not &lt;code&gt;uncons&lt;/code&gt; and vice-versa, but we can define an instance:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Choice&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; p f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _Cons = prism (\(x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (x:fs) bs) $ \ (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs) -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; fs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
     x:xs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; xs bs)
     []   -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse bs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
       x:xs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; xs [])
       [] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [] [])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us the following &lt;a href=&quot;https://hackage.haskell.org/packages/archive/lens/3.9.0.2/doc/html/Control-Lens-Prism.html&quot;&gt;&lt;code&gt;Prism&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;_Cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Prism&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; b) (a, &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; a) (b, &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now use it to &lt;code&gt;cons&lt;/code&gt; and &lt;code&gt;uncons&lt;/code&gt;, using the definitions from &lt;code&gt;Control.Lens.Cons&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = _Cons # (a,&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;uncons&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;^?_Cons
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That module also provides combinators that makes either a &lt;code&gt;Getter&lt;/code&gt;, &lt;code&gt;Setter&lt;/code&gt;, &lt;code&gt;Lens&lt;/code&gt; or &lt;code&gt;Traversal&lt;/code&gt; for each of &lt;code&gt;_head&lt;/code&gt; and &lt;code&gt;_tail&lt;/code&gt; depending on the restricted form of &lt;code&gt;_Cons&lt;/code&gt; you chose.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;_head&lt;/span&gt; = _Cons._1
&lt;span class=&quot;hljs-title&quot;&gt;_tail&lt;/span&gt; = _Cons._2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other side we only want to be able to &lt;code&gt;snoc&lt;/code&gt;, not use &lt;code&gt;tail&lt;/code&gt;, &lt;code&gt;init&lt;/code&gt; or &lt;code&gt;unsnoc&lt;/code&gt;, so let's define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Reviewed&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Snoc&lt;/span&gt; p f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _Snoc = unto $ \(&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; f b,x) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; f (x:b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: we &lt;em&gt;could&lt;/em&gt; also support &lt;code&gt;_init&lt;/code&gt; and &lt;code&gt;_tail&lt;/code&gt; and &lt;code&gt;unsnoc&lt;/code&gt;, but they will be &lt;em&gt;O(n)&lt;/em&gt;, even for ephemeral use, because we do not try to preserve any balance between the front and back lists.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;unto&lt;/code&gt; is used to define a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/lens/3.9.0.2/doc/html/Control-Lens-Review.html#g:1&quot;&gt;&lt;code&gt;Review&lt;/code&gt;&lt;/a&gt;, which is to a &lt;code&gt;Prism&lt;/code&gt; what a &lt;code&gt;Getter&lt;/code&gt; is to a &lt;code&gt;Lens&lt;/code&gt;. In practice it makes something that is like a &lt;code&gt;Prism&lt;/code&gt; in that you can apply &lt;code&gt;#&lt;/code&gt; to it, but nothing else.&lt;/p&gt;
&lt;p&gt;This is enough to permit us to use the stock definition of &lt;code&gt;snoc&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;snoc&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; a = _Snoc # (&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;,a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all of that we can finally play with our &lt;code&gt;Steque&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens.Internal.Review
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor.Identity
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Function (&lt;span class=&quot;hljs-title&quot;&gt;on&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] [a] &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (==) = (==) `on` toList
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare = compare `on` toList
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fmap f fs) (fmap f rs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = foldMap f fs `mappend` getDual (foldMap (&lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; . f) rs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs) = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &amp;lt;$&amp;gt; traverse f fs &amp;lt;*&amp;gt; backwards traverse f rs
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] []
  (&amp;lt;*&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs &amp;lt;|&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fs ++ reverse rs ++ fs') rs'
  empty = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [] []
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [a] []
  &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fs &amp;gt;&amp;gt;= toList . f) (bs &amp;gt;&amp;gt;= toListOf (backwards folded) . f)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mplus = (&amp;lt;|&amp;gt;)
  mzero = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [] []
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mappend = (&amp;lt;|&amp;gt;)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [] []
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Choice&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; p f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _Cons = prism (\(x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (x:fs) bs) $ \ (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs bs) -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; fs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
     x:xs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; xs bs)
     []   -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse bs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
       x:xs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (x,&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; xs [])
       [] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; [] [])
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Reviewed&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Snoc&lt;/span&gt; p f (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _Snoc = unto $ \(&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; f b,x) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; f (x:b)


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ uncons (snoc (cons &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (cons &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (snoc (empty :: &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;))) &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, our definition of a &lt;code&gt;Steque&lt;/code&gt; works passably well.&lt;/p&gt;
&lt;p&gt;We can snoc, cons, uncons, head, or tail all in &lt;em&gt;O(1)&lt;/em&gt; amortized time.&lt;/p&gt;
&lt;p&gt;but the &lt;code&gt;Monoid&lt;/code&gt;, &lt;code&gt;Alternative&lt;/code&gt; and &lt;code&gt;MonadPlus&lt;/code&gt; instances perform poorly, doing &lt;em&gt;O(n)&lt;/em&gt; work because it has to glue together potentially rather long lists:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs rs &amp;lt;|&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; fs' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (fs ++ reverse rs ++ fs') rs'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is that &lt;code&gt;Monoid&lt;/code&gt; performance that makes us sad, so let's do something about it.&lt;/p&gt;
&lt;h2 id=&quot;bootstrapping&quot;&gt;Bootstrapping&lt;/h2&gt;
&lt;p&gt;To solve that we turn to &lt;a href=&quot;http://www.usma.edu/eecs/SitePages/Chris%20Okasaki.aspx&quot;&gt;Chris Okasaki&lt;/a&gt;'s &lt;a href=&quot;http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf&quot;&gt;Purely Functional Data Structures&lt;/a&gt; once again, this time to find bootstrapping.&lt;/p&gt;
&lt;p&gt;Bootstrapping is a tool for defining a data structure with cheap concatenation by recursively storing it in itself.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Catenable&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Empty&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Catenable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we could build a &lt;code&gt;Catenable Steque&lt;/code&gt; out of our basic &lt;code&gt;Steque&lt;/code&gt; following Okasaki's recipe. Here the vocabulary of Tarjan is more accurate and extensible. Tarjan calls a &quot;catenable steque&quot; a c-steque, while Okasaki uses the less informative name &quot;catenable list.&quot;&lt;/p&gt;
&lt;p&gt;As with the pairing &lt;code&gt;Heap&lt;/code&gt;, recursion is simpler if we don't allow &lt;code&gt;Empty&lt;/code&gt; catenable substructures, and I'm only going to need non-empty catenable structures, though, so &lt;code&gt;Catenable&lt;/code&gt; simplifies to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Catenable&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Catenable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which advanced Haskell programmers in the audience may recognize as my old friend the &lt;a href=&quot;https://hackage.haskell.org/packages/archive/free/3.4.2/doc/html/Control-Comonad-Cofree.html&quot;&gt;cofree comonad&lt;/a&gt;! In the interest of retaining some semblance of accessibility, I'm not going to work through this exercise in its full generality.&lt;/p&gt;
&lt;p&gt;Now it is obvious how to concatenate a pair of catenable steques, we simply insert one into the other.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Steque&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &amp;lt;&amp;gt; bs = &lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a (snoc &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hrmm. That sounds suspiciously like the operation that drove our pairing heap.&lt;/p&gt;
&lt;p&gt;You can derive &lt;code&gt;cons&lt;/code&gt; and &lt;code&gt;snoc&lt;/code&gt; by just concatenating singleton catenable steques, and &lt;code&gt;uncons&lt;/code&gt; simply has to put back the leftovers if any into the underlying &lt;code&gt;Steque&lt;/code&gt;, which it can do because our &lt;code&gt;Steque&lt;/code&gt; supports &lt;em&gt;O(1)&lt;/em&gt; &lt;code&gt;cons&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;If we inline the definition of &lt;code&gt;Steque&lt;/code&gt; into &lt;code&gt;CSteque&lt;/code&gt; we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a [&lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a] [&lt;span class=&quot;hljs-type&quot;&gt;CSteque&lt;/span&gt; a]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and that looks a &lt;em&gt;lot&lt;/em&gt; like our pairing heap, just with different invariants.&lt;/p&gt;
&lt;p&gt;Hrmm.&lt;/p&gt;
&lt;h2 id=&quot;catenable-heaps&quot;&gt;Catenable Heaps&lt;/h2&gt;
&lt;p&gt;Finally, what we want looks kind of like a steque of heaps, but where the heaps can also act like steques of heaps, &lt;em&gt;ad infinitum&lt;/em&gt;. We can get there by mashing all the parts we've described together to get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This type represents a form of catenable non-empty pairing heap. The three lists of heaps in turn are:&lt;/p&gt;
&lt;p&gt;1.) the jumbled mess of heaps we haven't sorted relative to one another except partially via the heap property, followed by
2.) a list of heaps that do not overlap one another in key space in ascending order, followed by
3.) another list of heaps that do not overlap one another in key space in descending order.&lt;/p&gt;
&lt;p&gt;Now we can concatenate in &lt;em&gt;O(1)&lt;/em&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fby&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fby&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls rs) r = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls (r:rs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A number of operations remain trivial:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a _ _ _) = (i, a)

&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; k v = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k v [] [] []

&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; :: [(&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;,a)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; ((k0,v0):xs) = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr (\(k,v) r -&amp;gt; mix (singleton k v) r) (singleton k0 v0) xs
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; [] = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;empty Heap&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; :: [(&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;,a)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; ((k0,v0):xs) = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr (\(k,v) r -&amp;gt; fby (singleton k v) r) (singleton k0 v0) xs
&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; [] = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;empty Heap&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pop&lt;/code&gt; got a bit more complicated. We'll just pass it the 3 lists from our heap, as it doesn't use the key/value pair out front and we don't want to require the compiler to figure out to specialize on the constructor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; (x:xs) ls     rs = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; $ fbys (merge x xs) ls rs
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; []     (l:ls) rs = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; $ fbys l ls rs
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; []     []     rs = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  f:fs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (fbys f fs [])
  []   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; [] []) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls' rs'
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls []) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls $ rs' &amp;lt;&amp;gt; reverse ls'
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls rs) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls $ rs' &amp;lt;&amp;gt; reverse ls' &amp;lt;&amp;gt; rs
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize #7&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Computing with &lt;code&gt;fbys&lt;/code&gt; in &lt;code&gt;pop&lt;/code&gt; is somewhat unpleasant, but I don't have a cleaner way.&lt;/p&gt;
&lt;p&gt;Is there something where I can preserve the correctness of this but not have to move content
into the right hand reversed list and re-reverse it? Keep in mind it isn't sound to move
it into the left list, because we don't know the length of the left list and can only
move content left when the left list is empty.&lt;/p&gt;
&lt;p&gt;We could probably insert a pair of other heaps into the reversed list by building up a
chain of &lt;code&gt;fby&lt;/code&gt;s popping something off of the &lt;code&gt;ls'&lt;/code&gt; and smashing the other &lt;code&gt;ls'&lt;/code&gt; and &lt;code&gt;rs'&lt;/code&gt;
underneath it by using this function recursively. What does that look like?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and &lt;code&gt;mix&lt;/code&gt; also becomes more complex as it now has to deal with the extra concatenated components, pushing what it can into the nested pairing heap.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; x@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; al ar) y@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b bs bl br)
  | i &amp;lt;= j    = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a (y:pops &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; al ar) [] []
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b (x:pops bs bl br) [] []


&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x (y:ys) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ys &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  (z:zs) -&amp;gt; mix x y `mix` merge z zs
  []     -&amp;gt; mix x y
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x [] = x

&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; xs     []     [] = xs
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; (x:xs) ls     rs = [fbys (merge x xs) ls rs]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; []     (l:ls) rs = [fbys l ls rs]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; []     []     rs = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  f:fs -&amp;gt; [fbys f fs []]
  _    -&amp;gt; [] &lt;span class=&quot;hljs-comment&quot;&gt;-- caught above&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pops&lt;/code&gt; is a slight optimization of &lt;code&gt;pop&lt;/code&gt; that uses the fact that the result is winding up in a list subject to the heap property and need not be reduced all the way down to a &lt;code&gt;Maybe (Heap a)&lt;/code&gt; just yet.&lt;/p&gt;
&lt;p&gt;Finally, we can define a &lt;em&gt;useful&lt;/em&gt; conversion to a &lt;code&gt;Stream&lt;/code&gt; that can get some benefit out of stream fusion.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HeapState&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a !(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; (a -&amp;gt; a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith&lt;/span&gt; f h0 = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; step (maybe &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; h0) &lt;span class=&quot;hljs-type&quot;&gt;Unknown&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a xs ls rs))     = return $ &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b xs ls rs)) = return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)      $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; j b) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; j b) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; | c &amp;lt;- f a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i c) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i c) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)      $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) = return $ &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i,a) &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;
  step &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;    = return &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [1] step #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [0] streamHeapWith #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This doesn't quite hit the &lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.104.7401&quot;&gt;stream fusion&lt;/a&gt; goal of being made of a single loop that can fuse into other loops, due to the recursive calls to &lt;code&gt;pop&lt;/code&gt;. I leave it as an exercise for the reader to find a form that implements &lt;code&gt;pop&lt;/code&gt; via iterative &lt;code&gt;Skip&lt;/code&gt; steps and a more complex state -- In other words, I haven't bothered yet. ;)&lt;/p&gt;
&lt;p&gt;Putting it all together yields:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE BangPatterns #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE PatternGuards #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream.Monadic &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream.Size
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Util
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Bootstrapped _catenable_ non-empty pairing heaps&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a]&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Append two heaps where we know every key in the first occurs before every key in the second&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fby&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fby&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls rs) r = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls (r:rs)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Interleave two heaps making a new 'Heap'&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;mix&lt;/span&gt; x@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; al ar) y@(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b bs bl br)
  | i &amp;lt;= j    = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a (y:pops &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; al ar) [] []
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b (x:pops bs bl br) [] []


&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x (y:ys) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ys &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  (z:zs) -&amp;gt; mix x y `mix` merge z zs
  []     -&amp;gt; mix x y
&lt;span class=&quot;hljs-title&quot;&gt;merge&lt;/span&gt; x [] = x

&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;top&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a _ _ _) = (i, a)

&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; (x:xs) ls     rs = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; $ fbys (merge x xs) ls rs
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; []     (l:ls) rs = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; $ fbys l ls rs
&lt;span class=&quot;hljs-title&quot;&gt;pop&lt;/span&gt; []     []     rs = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  f:fs -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (fbys f fs [])
  []   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;singleton&lt;/span&gt; k v = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k v [] [] []

&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; :: [(&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;,a)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; ((k0,v0):xs) = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr (\(k,v) r -&amp;gt; mix (singleton k v) r) (singleton k0 v0) xs
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; [] = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;empty Heap&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; :: [(&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;,a)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; ((k0,v0):xs) = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr (\(k,v) r -&amp;gt; fby (singleton k v) r) (singleton k0 v0) xs
&lt;span class=&quot;hljs-title&quot;&gt;fromAscList&lt;/span&gt; [] = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;empty Heap&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Internals&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; [] []) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls' rs'
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls []) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls $ rs' &amp;lt;&amp;gt; reverse ls'
&lt;span class=&quot;hljs-title&quot;&gt;fbys&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls rs) ls' rs' = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ls $ rs' &amp;lt;&amp;gt; reverse ls' &amp;lt;&amp;gt; rs

&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; :: [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; xs     []     [] = xs
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; (x:xs) ls     rs = [fbys (merge x xs) ls rs]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; []     (l:ls) rs = [fbys l ls rs]
&lt;span class=&quot;hljs-title&quot;&gt;pops&lt;/span&gt; []     []     rs = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; reverse rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  f:fs -&amp;gt; [fbys f fs []]
  _    -&amp;gt; [] &lt;span class=&quot;hljs-comment&quot;&gt;-- caught above by the 'go as [] []' case&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Instances&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k a xs ls rs) = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k (f a) (fmap f &amp;lt;$&amp;gt; xs) (fmap f &amp;lt;$&amp;gt; ls) (fmap f &amp;lt;$&amp;gt; rs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FunctorWithIndex&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  imap f (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k a xs ls rs) = &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; k (f k a) (imap f &amp;lt;$&amp;gt; xs) (imap f &amp;lt;$&amp;gt; ls) (imap f &amp;lt;$&amp;gt; rs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; _ a xs ls rs) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; pop xs ls rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; f a
      &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; h  -&amp;gt; f a `mappend` go h
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE foldMap #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FoldableWithIndex&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  ifoldMap f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a xs ls rs) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; pop xs ls rs &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; f i a
      &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; h  -&amp;gt; f i a `mappend` go h
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE ifoldMap #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- this linearizes the heap&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f xs = fromAscList &amp;lt;$&amp;gt; traverse (traverse f) (itoList xs)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE traverse #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;TraversableWithIndex&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  itraverse f xs = fromAscList &amp;lt;$&amp;gt; traverse (\(k,v) -&amp;gt; (,) k &amp;lt;$&amp;gt; f k v) (itoList xs)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE itraverse #-}&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HeapState&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a !(&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; (a -&amp;gt; a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith&lt;/span&gt; f h0 = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; step (maybe &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; h0) &lt;span class=&quot;hljs-type&quot;&gt;Unknown&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a xs ls rs))     = return $ &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b xs ls rs)) = return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)      $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; j b) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; j b) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; | c &amp;lt;- f a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i c) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i c) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)      $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) = return $ &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i,a) &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;
  step &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;    = return &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [1] step #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [0] streamHeapWith #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; (a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)
&lt;span class=&quot;hljs-title&quot;&gt;streamHeapWith0&lt;/span&gt; f h0 = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; step (maybe &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; h0) &lt;span class=&quot;hljs-type&quot;&gt;Unknown&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; i a xs ls rs))     = return $ &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a (&lt;span class=&quot;hljs-type&quot;&gt;Heap&lt;/span&gt; j b xs ls rs)) = return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; j b) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; j b) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt;  $ maybe &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Start&lt;/span&gt; $ pop xs ls rs
      &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; c  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt;  $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i c) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i c) $ pop xs ls rs
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) $ maybe (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) (&lt;span class=&quot;hljs-type&quot;&gt;Ready&lt;/span&gt; i a) $ pop xs ls rs
  step (&lt;span class=&quot;hljs-type&quot;&gt;Final&lt;/span&gt; i a) = return $ &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i,a) &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt;
  step &lt;span class=&quot;hljs-type&quot;&gt;Finished&lt;/span&gt; = return &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [1] step #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [0] streamHeapWith0 #-}&lt;/span&gt;



&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ (fromList [(&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;hi&quot;&lt;/span&gt;),(&lt;span class=&quot;hljs-number&quot;&gt;20&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;there&quot;&lt;/span&gt;)] `mix` singleton &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;) `fby` singleton &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've left figuring out how to write &lt;code&gt;_Cons&lt;/code&gt; and &lt;code&gt;_Snoc&lt;/code&gt; as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;With that we can finally concatenate heaps and mix them together as needed, and the stream fusion combinators can be used after the fact to spit out a stream of values that have been merged by our desired concept of addition. What has happened is that we for the most part are able to punt considering anything later in the chain of concatenations until after we've fully explored the stuff nearer to hand.&lt;/p&gt;
&lt;p&gt;In practice this made a couple of orders of magnitude difference in the performance of the resulting code, so all this theoretical nonsense paid off.&lt;/p&gt;
&lt;p&gt;I'd like a version of this that let's me reach the asymptotic bounds on set union set and reached by Erik Demaine et al.'s tour de force &lt;a href=&quot;http://dl.acm.org/citation.cfm?id=338634&quot;&gt;Adaptive set intersections, unions, and differences&lt;/a&gt;, but I don't &lt;em&gt;think&lt;/em&gt; we can get there given the extra constraints that we don't fully know the contents of the streams we're skipping over in advance.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 23 2013&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edited September 14th, 2013&lt;/em&gt;: Mihály Bárász pointed out to me that I had over-simplified the pairing heap implementation. I've rectified that by replacing &lt;code&gt;foldl mix&lt;/code&gt; with &lt;code&gt;merge&lt;/code&gt; uniformly throughout the code above. This makes a noticeable improvement in performance.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/revisiting-matrix-multiplication-part-5/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Quine: Shader Toys</title><link>https://comonad.com/reader/2014/quine-shader-toys/</link><guid isPermaLink="false">https://comonad.com/reader/2014/quine-shader-toys/</guid><pubDate>Tue, 28 Oct 2014 12:00:00 GMT</pubDate><category>Demo</category><description>&lt;p&gt;Edward Kmett · 28 October 2014 · repository&lt;/p&gt;&lt;p&gt;Quine existed primarily to test the then-new &lt;a href=&quot;https://hackage.haskell.org/package/gl&quot;&gt;&lt;code&gt;gl&lt;/code&gt; package&lt;/a&gt;, the raw OpenGL bindings for Haskell (&lt;a href=&quot;https://github.com/ekmett/gl&quot;&gt;source on GitHub&lt;/a&gt;). It doubled as a graphics playground. Its README puts it simply:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is just me waxing nostalgic and throwing together some code for playing with graphics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These two shader toys now run here. Choose a shader, pause it, or move through time. Generators also lets you look around by dragging the image or using the arrow keys.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/quine-shader-toys/#quine-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;dodecahedron&quot;&gt;Dodecahedron&lt;/h2&gt;
&lt;p&gt;Twenty triangular frames form an interlocking compound. The shader combines distance estimates for triangular prisms, marches a ray through the resulting field, and shades the surface with two lights, shadows, and ambient occlusion. The camera circles it as time advances.&lt;/p&gt;
&lt;p&gt;The example first appeared in Quine on &lt;a href=&quot;https://github.com/ekmett/quine/commit/33eb8bc64a01103b1c0ff17448848fc254ed5371&quot;&gt;28 October 2014&lt;/a&gt;. Its source credits &lt;a href=&quot;https://www.shadertoy.com/view/MdS3Rw&quot;&gt;this Shadertoy&lt;/a&gt; as the starting point.&lt;/p&gt;
&lt;h2 id=&quot;generators-redux&quot;&gt;Generators Redux&lt;/h2&gt;
&lt;p&gt;A camera follows a reflective ball through a repeating fractal structure. This is &lt;strong&gt;Generators Redux by Kali&lt;/strong&gt;, reworked by &lt;strong&gt;eiffie&lt;/strong&gt; for speed and ANGLE compatibility, then included in Quine on &lt;a href=&quot;https://github.com/ekmett/quine/commit/2134254d4a6c8915b3eab772a23b9d58512cbc4a&quot;&gt;8 November 2014&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The shader keeps its original &lt;a href=&quot;https://www.shadertoy.com/view/lsXGWl&quot;&gt;Shadertoy attribution&lt;/a&gt; and &lt;strong&gt;&lt;a href=&quot;https://creativecommons.org/licenses/by-nc-sa/3.0/&quot;&gt;CC BY-NC-SA 3.0 license&lt;/a&gt;&lt;/strong&gt;. The browser adaptation of this shader is distributed under the same license.&lt;/p&gt;
&lt;h2 id=&quot;from-opengl-to-the-browser&quot;&gt;From OpenGL to the browser&lt;/h2&gt;
&lt;p&gt;This is a new browser companion to the historical repository, built in September 2026. The date in the archive marks the first of these shader examples in Quine, rather than the date of this page.&lt;/p&gt;
&lt;p&gt;The two fragment shaders run directly on the GPU through WebGL 2. Their distance fields, ray marching, shading, and camera paths are retained. The port changes the desktop GLSL header to GLSL ES, supplies the uniforms from the browser, moves a time-dependent global initializer into the fragment entry point, and renames a function that overlaps the browser shader language’s built-in &lt;code&gt;texture&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;The surrounding Haskell/SDL application is preserved as source. This companion replaces its window and rendering loop with a small browser host; it does not compile the Haskell application to WebAssembly.&lt;/p&gt;
&lt;p&gt;“Detail” changes the rendering resolution. The demo limits its frame rate to 30 frames per second, pauses while off screen or in a hidden tab, and starts paused when reduced motion is requested.&lt;/p&gt;
&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2014/quine-shader-toys/&quot;&gt;Quine on GitHub&lt;/a&gt;, preserved at &lt;a href=&quot;https://github.com/ekmett/quine/tree/8e5ed1a91b0ca52b442ccf4da7f7acc878e4468b&quot;&gt;commit 8e5ed1a&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/quine/original/quine-source.zip&quot;&gt;Complete original Quine source archive&lt;/a&gt;, including the Haskell application, shaders, README, and licenses.&lt;/li&gt;
&lt;li&gt;Dodecahedron: &lt;a href=&quot;https://comonad.com/assets/quine/original/dodecahedron.frag&quot;&gt;original GLSL&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/quine/dodecahedron.frag&quot;&gt;browser GLSL&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Generators Redux: &lt;a href=&quot;https://comonad.com/assets/quine/original/generators.frag&quot;&gt;original GLSL&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/quine/generators.frag&quot;&gt;browser GLSL&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/quine/original/Toy.hs&quot;&gt;Original Haskell shader host&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/quine-demo.js&quot;&gt;browser host&lt;/a&gt; · &lt;a href=&quot;https://comonad.com/assets/quine/original/LICENSE&quot;&gt;Quine license&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/quine-shader-toys/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Getting a Quick Fix of Comonads</title><link>https://comonad.com/reader/talks/youtube-8r1lji4Pzsg/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-8r1lji4Pzsg/</guid><pubDate>Wed, 17 Sep 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Kenneth Foner · 17 September 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;8r1lji4Pzsg&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8r1lji4Pzsg&quot;&gt;Watch on YouTube&lt;/a&gt; · 58 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Kenneth Foner's Comonad talk at the Boston Haskell meetup, September 17, 2014.&lt;br&gt;
Code and slides: &lt;a href=&quot;https://github.com/kwf/ComonadSheet&quot;&gt;https://github.com/kwf/ComonadSheet&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/kwf/ComonadSheet&quot;&gt;slides and code&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-8r1lji4Pzsg/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Ur/Web</title><link>https://comonad.com/reader/talks/youtube-8n5ubDe9FAA/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-8n5ubDe9FAA/</guid><pubDate>Wed, 20 Aug 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Adam Chlipala · 20 August 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;8n5ubDe9FAA&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8n5ubDe9FAA&quot;&gt;Watch on YouTube&lt;/a&gt; · 64 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Adam Chlipala agreed to come out to Boston Haskell and give a talk on the Ur/Web programming language on August 20th, 2014.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-8n5ubDe9FAA/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Letter to a Young Haskell Enthusiast</title><link>https://comonad.com/reader/2014/letter-to-a-young-haskell-enthusiast/</link><guid isPermaLink="false">https://comonad.com/reader/2014/letter-to-a-young-haskell-enthusiast/</guid><pubDate>Fri, 01 Aug 2014 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 1 August 2014&lt;/p&gt;&lt;p&gt;*The following letter is not about what &quot;old hands&quot; know and newcomers do not. Instead, it is about lessons that we all need to learn more than once, and remind ourselves of. It is about tendencies that are common, and understandable, and come with the flush of excitement of learning any new thing that we understand is important, and about the difficulty, always, in trying to decide how best to convey that excitement and sense of importance to others, in a way that they will listen. It is written more specifically, but only because I have found that if we don't talk specifics as well as generalities, the generalities make no sense. This holds for algebraic structures, and it holds for other, vaguer concepts no less. It is a letter full of things I want to remember, as well as of advice I want to share. I expect I will want to remind myself of it when I encounter somebody who is wrong on the internet, which, I understand, may occur on rare occasion.&lt;br&gt;
*&lt;/p&gt;
&lt;p&gt;You’ve recently entered the world of strongly typed functional programming, and you’ve decided it is great. You’ve written a program or two or a library or two, and you’re getting the hang of it. You hop on IRC and hear new words and ideas every day. There are always new concepts to learn, new libraries to explore, new ways to refactor your code, new typeclasses to make instances of.&lt;/p&gt;
&lt;p&gt;Now, you’re a social person, and you want to go forth and share all the great things you’ve learned. And you have learned enough to distinguish some true statements from some false statements, and you want to go and slay all the false statements in the world.&lt;/p&gt;
&lt;p&gt;Is this really what you want to do? Do you want to help people, do you want to teach people new wonderful things? Do you want to share the things that excite you? Or do you want to feel better about yourself, confirm that you are programming better, confirm that you are smarter and know more, reassure yourself that your adherence to a niche language is ok by striking out against the mainstream? Of course, you want to do the former. But a part of you probably secretly wants to do the latter, because in my experience that part is in all of us. It is our ego, and it drives us to great things, but it also can hold us back, make us act like jerks, and, worst of all, stand in the way of communicating with others about what we truly care about.&lt;/p&gt;
&lt;p&gt;Haskell wasn’t built on great ideas, although it has those. It was built on a culture of how ideas are treated. It was not built on slaying others’ dragons, but on finding our own way; not tearing down rotten ideas (no matter how rotten) but showing by example how we didn’t need those ideas after all.&lt;/p&gt;
&lt;p&gt;In functional programming, our proofs are not by contradiction, but by construction. If you want to teach functional programming, or preach functional programming, or just to even have productive discussions as we all build libraries and projects together, it will serve you well to learn that ethic.&lt;/p&gt;
&lt;p&gt;You know better than the next developer, or so you think. This is because of something you have learned. So how do you help them want to learn it too? You do not tell them this is a language for smart people. You do not tell them you are smart because you use this language. You tell them that types are for fallible people, like we all are. They help us reason and catch our mistakes, because while software has grown more complex, we’re still stuck with the same old brains. If they tell you they don’t need types to catch errors, tell them that they must be much smarter than you, because you sure do. But even more, tell them that all the brainpower they use to &lt;strong&gt;not&lt;/strong&gt; need types could turn into even greater, bigger, and more creative ideas if they let the compiler help them.&lt;/p&gt;
&lt;p&gt;This is not a language for clever people, although there are clever things that can be done in this language. It is a language for simple things and clever things alike, and sometimes we want to be simple, and sometimes we want to be clever. But we don’t give bonus points for being clever. Sometimes, it’s just fun, like solving a crossword puzzle or playing a tricky Bach prelude, or learning a tango. We want to keep simple things simple so that tricky things are possible.&lt;/p&gt;
&lt;p&gt;It is not a language that is “more mathematical” or “for math” or “about math”. Yes, in a deep formal sense, programming is math. But when someone objects to this, this is not because they are a dumb person, a bad person, or a malicious person. They object because they have had a bad notion of math foisted on them. “Math” is the thing that people wield over them to tell them they are not good enough, that they cannot learn things, that they don’t have the mindset for it. That’s a dirty lie. Math is not calculation — that’s what computers are for. Nor is math just abstract symbols. Nor is math a prerequisite for Haskell. If anything, Haskell might be what makes somebody find math interesting at all. Our equation should not be that math is hard, and so programming is hard. Rather, it should be that programming can be fun, and this means that math can be fun too. Some may object that programming is not only math, because it is engineering as well, and creativity, and practical tradeoffs. But, surprisingly, these are also elements of the practice of math, if not the textbooks we are given.&lt;/p&gt;
&lt;p&gt;I have known great Haskell programmers, and even great computer scientists who know only a little linear algebra maybe, or never bothered to pick up category theory. You don’t &lt;strong&gt;need&lt;/strong&gt; that stuff to be a great Haskell programmer. It &lt;strong&gt;might&lt;/strong&gt; be one way. The only thing you need category theory for is to take great categorical and mathematical concepts from the world and import them back to programming, and translate them along the way so that others don’t need to make the same journey you did. And you don’t even need to do that, if you have patience, because somebody else will come along and do it for you, eventually.&lt;/p&gt;
&lt;p&gt;The most important thing, though not hardest, about teaching and spreading knowledge is to emphasize that this is for &lt;strong&gt;everyone&lt;/strong&gt;. Nobody is too young, too inexperienced, too old, too set in their ways, too excitable, insufficiently mathematical, etc. Believe in everyone, attack nobody, even the trolliest.&lt;a href=&quot;https://comonad.com/reader/2014/letter-to-a-young-haskell-enthusiast/#fn&quot;&gt;*&lt;/a&gt; Attacking somebody builds a culture of sniping and argumentativeness. It spreads to the second trolliest, and soforth, and then eventually to an innocent bystander who just says the wrong thing to spark bad memories of the last big argument.&lt;/p&gt;
&lt;p&gt;The hardest thing, and the second most important, is to put aside your pride. If you want to teach people, you have to empathize with how they think, and also with how they feel. If your primary goal is to spread knowledge, then you must be relentlessly self-critical of anything you do or say that gets in the way of that. And you don’t get to judge that — others do. And you must just believe them. I told you this was hard. So if somebody finds you offputting, that’s your fault. If you say something and somebody is hurt or takes offense, it is not their fault for being upset, or feeling bad. This is not about what is abstractly hurtful in a cosmic sense; it is about the fact that you have failed, concretely, to communicate as you desired. So accept the criticism, apologize for giving offense (not just for having upset someone but also for what you did to hurt them), and attempt to learn why they feel how they feel, for next time.&lt;/p&gt;
&lt;p&gt;Note that if you have made somebody feel crummy, they may not be in a mood to explain why or how, because their opinion of you has already plummeted. So don’t declare that they must or should explain themselves to you, although you may politely ask. Remember that knowledge does not stand above human behavior. Often, you don't need to know exactly why a person feels the way they do, only that they do, so you can respect that. If you find yourself demanding explanations, ask yourself, if you knew this thing, would that change your behavior? How? If not, then learn to let it go.&lt;/p&gt;
&lt;p&gt;Remember also that they were put off by your actions, not by your existence. It is easy to miss this distinction and react defensively. &quot;Fight-or-flight&quot; stands in the way of clear thinking and your ability to empathize; try taking a breath and maybe a walk until the adrenaline isn't derailing your true intentions.&lt;/p&gt;
&lt;p&gt;Will this leave you satisfied? That depends. If your goal is to understand everything and have everybody agree with regards to everything that is in some sense objectively true, it will not. If your goal is to have the widest, nicest, most diverse, and most fun Haskell community possible, and to interact in an atmosphere of mutual respect and consideration, then it is the only thing that will leave you satisfied.&lt;/p&gt;
&lt;p&gt;If you make even the most modest (to your mind) mistake, be it in social interaction or technical detail, be quick to apologize and retract, and do so freely. What is there to lose? Only your pride. Who keeps track? Only you. What is there to gain? Integrity, and ultimately that integrity will feel far more fulfilling than the cheap passing thrills of cutting somebody else down or deflecting their concerns.&lt;/p&gt;
&lt;p&gt;Sometimes it may be, for whatever reason, that somebody doesn’t want to talk to you, because at some point your conversation turned into an argument. Maybe they did it, maybe you did it, maybe you did it together. It doesn’t matter, learn to walk away. Learn from the experience how to communicate better, how to avoid that pattern, how to always be the more positive, more friendly, more forward-looking. Take satisfaction in the effort in that. Don’t talk about them behind their back, because that will only fuel your own bad impulses. Instead, think about how you can change.&lt;/p&gt;
&lt;p&gt;Your self-esteem doesn’t need your help. You may feel you need to prove yourself, but you don't. Other people, in general, have better things to do with their time than judge you, even when you may sometimes feel otherwise. You know you’re talented, that you have learned things, and built things, and that this will be recognized in time. Nobody else wants to hear it from you, and the more they hear it, the less they will believe it, and the more it will distract from what you &lt;strong&gt;really&lt;/strong&gt; want, which is not to feed your ego, not to &lt;strong&gt;be&lt;/strong&gt; great, but to &lt;strong&gt;accomplish&lt;/strong&gt; something great, or even just to find others to &lt;strong&gt;share&lt;/strong&gt; something great with. In fact, if anyone's self-esteem should be cared for, it is that of the people you are talking to. The more confident they are in their capacity and their worth, the more willing they will be to learn new things, and to acknowledge that their knowledge, like all of ours, is limited and partial. You must believe in yourself to be willing to learn new things, and if you want to cultivate more learners, you must cultivate that self-belief in others.&lt;/p&gt;
&lt;p&gt;Knowledge is not imposing. Knowledge is fun. Anyone, given time and inclination, can acquire it. Don’t only lecture, but continue to learn, because there is always much more than you know. (And if there wasn’t, wow, that would be depressing, because what would there be to learn next?) Learn to value all opinions, because they all come from experiences, and all those experiences have something to teach us. Dynamic typing advocates have brought us great leaps in JIT techniques. If you’re interested in certain numerical optimizations, you need to turn to work pioneered in C++ or Fortran. Like you, I would rather write in Haskell. But it is not just the &lt;strong&gt;tools&lt;/strong&gt; that matter but the &lt;strong&gt;ideas&lt;/strong&gt;, and you will find they come from everywhere.&lt;/p&gt;
&lt;p&gt;In fact, we have so much to learn that we direct our learning by setting up barriers — declaring certain tools, fields, languages, or communities not worth our time. This isn’t because they have nothing to offer, but it is a crutch for us to shortcut evaluating too many options all at once. It is fine, and in fact necessary, to narrow the scope of your knowledge to increase its depth. But be glad that others are charting other paths! Who knows what they will bring back from those explorations.&lt;/p&gt;
&lt;p&gt;If somebody is chatting about programming on the internet, they’re already ahead of the pack, already interested in craft and knowledge. You may not share their opinions, but you have things to learn from one another, always. Maybe the time and place aren’t right to share ideas and go over disputes. That’s ok. There will be another time and place, or maybe there won’t be. There is a big internet full of people, and you don’t need to be everybody’s friend or everybody’s mentor. You should just avoid being anybody’s enemy, because your time and theirs is too precious to waste it on hard feelings instead of learning new cool stuff.&lt;/p&gt;
&lt;p&gt;This advice is not a one-time proposition. Every time we learn something new and want to share it, we face these issues all over again -- the desire to proclaim, to overturn received wisdom all at once -- and the worse the received wisdom, the more vehemently we want to strike out. But if we are generous listeners and attentive teachers, we not only teach better and spread more knowledge, but also learn more, and enjoy ourselves more in the process. To paraphrase Rilke’s “Letter to a Young Poet”: Knowledge is good if it has sprung from necessity. In this nature of its origin lies the judgement of it: there is no other.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to the various folks in and around the Haskell world who have helped me refine this article. I don't name you only because I don't want to imply your endorsement, or give what is still, at base, a very personal take, any particular sort of imprimatur of a broader group of people, all of whom I suspect will disagree among themselves and with me about various specifics.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span id=&quot;fn&quot;&gt;&lt;/span&gt;&lt;strong&gt;*:&lt;/strong&gt; It has been pointed out to me that this advice is not universal. Clearly there are some things that deserve more pointed responses. Bigotry, outright harassment and poisonous behavior, etc. So please read this paragraph only as it applies to talking about technical issues, not as regards to many other things, where there are people &lt;a href=&quot;http://modelviewculture.com/&quot;&gt;better equipped than me&lt;/a&gt; to give advice.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/letter-to-a-young-haskell-enthusiast/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>On Hask</title><link>https://comonad.com/reader/talks/kmett-2014-on-hask/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2014-on-hask/</guid><pubDate>Wed, 16 Jul 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 16 July 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Klwkt9oJwg0&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Klwkt9oJwg0&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;On Hask — Boston Haskell at Akamai, Cambridge.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Klwkt9oJwg0&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2014-on-hask/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>CUFP 2014 Call For Presentations</title><link>https://comonad.com/reader/2014/cufp-cfp/</link><guid isPermaLink="false">https://comonad.com/reader/2014/cufp-cfp/</guid><pubDate>Sun, 20 Apr 2014 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 20 April 2014&lt;/p&gt;&lt;span id=&quot;more-923&quot;&gt;&lt;/span&gt;&lt;p&gt;**Workshop for&lt;br&gt;
Commercial Users of Functional Programming 2014&lt;br&gt;
Sponsored by SIGPLAN&lt;br&gt;
&lt;a href=&quot;http://cufp.org/conference&quot;&gt;CUFP 2014&lt;/a&gt;&lt;br&gt;
Co-located with &lt;a href=&quot;http://icfpconference.org/icfp2014&quot;&gt;ICFP 2014&lt;/a&gt;&lt;br&gt;
Gothenburg, Sweden&lt;br&gt;
Sep 4-6&lt;br&gt;
Talk Proposal Submission Deadline: 27 June 2014&lt;br&gt;
**&lt;br&gt;
&lt;a href=&quot;http://goo.gl/5BJLul&quot;&gt;CUFP 2014 Presentation Submission Form&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The annual CUFP workshop is a place where people can see how others are using functional programming to solve real world problems; where practitioners meet and collaborate; where language designers and users can share ideas about the future of their favorite language; and where one can learn practical techniques and approaches for putting functional programming to work.&lt;/p&gt;
&lt;h4 id=&quot;giving-a-cufp-talk&quot;&gt;Giving a CUFP Talk&lt;/h4&gt;
&lt;p&gt;If you have experience using functional languages in a practical setting, we invite you to submit a proposal to give a talk at the workshop. We're looking for two kinds of talks:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Experience reports&lt;/strong&gt; are typically 25 minutes long, and aim to inform participants about how functional programming plays out in real-world applications, focusing especially on lessons learned and insights gained. Experience reports don't need to be highly technical; reflections on the commercial, management, or software engineering aspects are, if anything, more important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical talks&lt;/strong&gt; are also 25 minutes long, and should focus on teaching the audience something about a particular technique or methodology, from the point of view of someone who has seen it play out in practice. These talks could cover anything from techniques for building functional concurrent applications, to managing dynamic reconfigurations, to design recipes for using types effectively in large-scale applications. While these talks will often be based on a particular language, they should be accessible to a broad range of programmers.&lt;/p&gt;
&lt;p&gt;We strongly encourage submissions from people in communities that are underrepresented in functional programming, including but not limited to women; people of color; people in gender, sexual and romantic minorities; people with disabilities; people residing in Asia, Africa, or Latin America; and people who have never presented at a conference before. We recognize that inclusion is an important part of our mission to promote functional programming. So that CUFP can be a safe environment in which participants openly exchange ideas, we abide by the &lt;a href=&quot;http://www.sigplan.org/Resources/Policies/Anti-harassment&quot;&gt;SIGPLAN Conference Anti-Harassment Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in offering a talk, or nominating someone to do&lt;br&gt;
so, please submit your presentation before 27 June 2014 via the&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://goo.gl/5BJLul&quot;&gt;CUFP 2014 Presentation Submission Form&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You do not need to submit a paper, just a short proposal for your talk! There will be a short scribe's report of the presentations and discussions but not of the details of individual talks, as the meeting is intended to be more a discussion forum than a technical interchange.&lt;/p&gt;
&lt;p&gt;Nevertheless, presentations will be video taped and presenters will be expected to sign an ACM copyright release form.&lt;/p&gt;
&lt;p&gt;Note that we will need all presenters to register for the CUFP workshop and travel to Gothenburg at their own expense.&lt;/p&gt;
&lt;h4 id=&quot;program-committee&quot;&gt;Program Committee&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/&quot;&gt;Edward Kmett&lt;/a&gt; (McGraw Hill Financial), co-chair&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://monkey.org/~marius&quot;&gt;Marius Eriksen&lt;/a&gt; (Twitter, Inc.), co-chair&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://soostone.com/&quot;&gt;Ozgun Ataman&lt;/a&gt; (Soostone, Inc.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://catamorphism.org/&quot;&gt;Tim Chevalier&lt;/a&gt; (AlephCloud)&lt;/li&gt;
&lt;li&gt;Derek Elkins (Now Business Intelligence)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://matt.might.net/&quot;&gt;Matthew Might&lt;/a&gt; (University of Utah)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://richardminerich.com/&quot;&gt;Richard Minerich&lt;/a&gt; (Bayard Rock)&lt;/li&gt;
&lt;li&gt;Audrey Tang (Apple, Inc.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/retronym&quot;&gt;Jason Zaugg&lt;/a&gt; (Typesafe)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;more-information&quot;&gt;More information&lt;/h4&gt;
&lt;p&gt;For more information on CUFP, including videos of presentations from&lt;br&gt;
previous years, take a look at the CUFP website at &lt;a href=&quot;http://cufp.org/&quot;&gt;cufp.org&lt;/a&gt;. Note that presenters, like other attendees, will need to register for the event. Presentations will be video taped and presenters will be expected to sign an ACM copyright release form. Acceptance and rejection letters will be sent out by July 16th.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;guidance&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;guidance-on-giving-a-great-cufp-talk&quot;&gt;Guidance on giving a great CUFP talk&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Focus on the interesting bits&lt;/strong&gt;: Think about what will distinguish your talk, and what will engage the audience, and focus there. There are a number of places to look for those interesting bits.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Setting&lt;/strong&gt;: FP is pretty well established in some areas, including formal verification, financial processing and server-sid web-services. An unusual setting can be a source of interest. If you're deploying FP-based mobile UIs or building servers on oil rigs, then the challenges of that scenario are worth focusing on. Did FP help or hinder in adapting to the setting?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technology&lt;/strong&gt;: The CUFP audience is hungry to learn about how FP techniques work in practice. What design patterns have you applied, and to what areas? Did you use functional reactive programming for user interfaces, or DSLs for playing chess, or fault-tolerant actors for large scale geological data processing? Teach us something about the techniques you used, and why we should consider using them ourselves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Getting things done&lt;/strong&gt;: How did you deal with large software development in the absence of a myriad of pre-existing support that are often expected in larger commercial environments (IDEs, coverage tools, debuggers, profilers) and without larger, proven bodies of libraries? Did you hit any brick walls that required support from the community?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don't just be a cheerleader&lt;/strong&gt;: It's easy to write a rah-rah talk about how well FP worked for you, but CUFP is more interesting when the talks also spend time on what _doesn't_ work. Even when the results were all great, you should spend more time on the challenges along the way than on the parts that went smoothly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/cufp-cfp/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Functorial Query Language</title><link>https://comonad.com/reader/talks/youtube-Q0m8baqBrk4/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-Q0m8baqBrk4/</guid><pubDate>Wed, 16 Apr 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Ryan Wisnesky · 16 April 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;Q0m8baqBrk4&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Q0m8baqBrk4&quot;&gt;Watch on YouTube&lt;/a&gt; · 54 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Ryan Wisnesky came out to give us a talk at Boston Haskell on April 16th, 2014 based on joint work with David Spivak on new ways to think about data and databases using category theory, along with a new tool they have been building to put these ideas into practice.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-Q0m8baqBrk4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Quick Introduction To Haskell</title><link>https://comonad.com/reader/talks/youtube-IAYNk951_xk/</link><guid isPermaLink="false">https://comonad.com/reader/talks/youtube-IAYNk951_xk/</guid><pubDate>Wed, 16 Apr 2014 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Tim Braje · 16 April 2014&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;IAYNk951_xk&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=IAYNk951_xk&quot;&gt;Watch on YouTube&lt;/a&gt; · 54 minutes&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Back at the beginning of 2014, the membership of Boston Haskell had recently begun to expand very rapidly. We'd gone from 20 to 60 attendees almost overnight. Consequently, A &quot;why you should care about Haskell&quot; talk seemed to be in order, so Tim Braje gave us all &quot;A Quick Introduction to Haskell&quot; on April 16th, 2014.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/youtube-IAYNk951_xk/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Catamorphisms</title><link>https://comonad.com/reader/2014/recursion-schemes-catamorphisms/</link><guid isPermaLink="false">https://comonad.com/reader/2014/recursion-schemes-catamorphisms/</guid><pubDate>Tue, 15 Apr 2014 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 April 2014&lt;/p&gt;&lt;h2 id=&quot;description&quot;&gt;Description&lt;/h2&gt;
&lt;p&gt;Catamorphisms are generalizations of the concept of a fold in functional programming. A &lt;i&gt;catamorphism&lt;/i&gt; deconstructs a data structure with an F-algebra for its underlying functor.&lt;/p&gt;
&lt;h2 id=&quot;history&quot;&gt;History&lt;/h2&gt;
&lt;p&gt;The name catamorphism appears to have been chosen by Lambert Meertens &lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[1]&lt;/a&gt;&lt;/span&gt;. The category theoretic machinery behind these was resolved by Grant Malcolm &lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[2]&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[3]&lt;/a&gt;&lt;/span&gt;, and they were popularized by Meijer, Fokkinga and Paterson&lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[4]&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[5]&lt;/a&gt;&lt;/span&gt;. The name comes from the Greek 'κατα-' meaning &quot;downward or according to&quot;. A useful mnemonic is to think of a catastrophe destroying something.&lt;br&gt;&lt;br&gt;&lt;b&gt;Notation&lt;/b&gt;&lt;br&gt;A catamorphism for some F-algebra (X,f) is denoted &lt;nobr&gt;(|f|)&lt;sub&gt;F&lt;/sub&gt;&lt;/nobr&gt;. When the functor F can be determined unambiguously, it is usually written &lt;nobr&gt;(|φ|)&lt;/nobr&gt; or &lt;nobr&gt;&lt;code&gt;cata&lt;/code&gt; φ&lt;/nobr&gt;. Due to this choice of notation, a catamorphism is sometimes called a banana and the &lt;nonr&gt;(|.|) notation is sometimes referred to as banana brackets.&lt;/nonr&gt;&lt;/p&gt;
&lt;h2 id=&quot;haskell-implementation&quot;&gt;Haskell Implementation&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f a = f a -&amp;gt; a&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;outF&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f = f . fmap (cata f) . outF
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;alternate-definitions&quot;&gt;Alternate Definitions&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f = hylo f outF
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f = para (f . fmap fst)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;duality&quot;&gt;Duality&lt;/h2&gt;
&lt;p&gt;A catamorphism is the categorical dual of an anamorphism.&lt;/p&gt;
&lt;h2 id=&quot;derivation&quot;&gt;Derivation&lt;/h2&gt;
&lt;p&gt;If (μF,in&lt;sub&gt;F&lt;/sub&gt;) is the initial F-algebra for some endofunctor F and (X,φ) is an F-algebra, then there is a unique F-algebra homomorphism from (μF,in&lt;sub&gt;F&lt;/sub&gt;) to (X,φ), which we denote &lt;nobr&gt;(|φ|)&lt;sub&gt;F&lt;/sub&gt;&lt;/nobr&gt;.&lt;/p&gt;
&lt;p&gt;That is to say, the following diagram commutes:&lt;/p&gt;
&lt;div style=&quot;margin-left:auto;margin-right:auto;text-align:center&quot;&gt;&lt;a href=&quot;https://comonad.com/haskell/catamorphism-diagram.png&quot; style=&quot;background-color:transparent&quot;&gt;&lt;img alt=&quot;Illustration from Catamorphisms&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/haskell/catamorphism-diagram.png&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2 id=&quot;laws&quot;&gt;Laws&lt;/h2&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;2&quot; width=&quot;80%&quot;&gt; 
  &lt;tbody&gt; 
    &lt;tr&gt;&lt;th&gt;Rule&lt;/th&gt;&lt;th&gt;Haskell&lt;/th&gt;&lt;/tr&gt; 
    &lt;tr&gt;&lt;th&gt;cata-cancel&lt;/th&gt; 
        &lt;td&gt;&lt;pre&gt;cata phi . InF = phi . fmap (cata phi)&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt; &lt;th&gt;cata-refl&lt;/th&gt;
         &lt;td&gt;&lt;pre&gt;cata InF = id&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt; &lt;th&gt;cata-fusion&lt;/th&gt;
         &lt;td&gt;&lt;pre&gt;f . phi = phi . fmap f =&amp;gt; &lt;br&gt;f . cata phi = cata phi&lt;/pre&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt; &lt;th&gt;cata-compose&lt;/th&gt; 
         &lt;td&gt;&lt;pre&gt;eps :: forall x. f x -&amp;gt; g x =&amp;gt;&lt;br&gt;cata phi . cata (In . eps) =&lt;br&gt;cata (phi . eps)&lt;/pre&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;
&lt;p&gt;The underlying functor for a string of characters and its fixed point.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;StrF&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; x | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Str&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;StrF&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;nil&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Str&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Str&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Str&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; x xs = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x xs)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;StrF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (f &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
  fmap f &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The length of a string as a catamorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Str&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt; = cata phi &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a b) = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + b
  phi &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The underlying functor for the natural numbers:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NatF&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NatF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NatF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; z) = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; (f z)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Addition as a catamorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;plus&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;plus&lt;/span&gt; n = cata phi &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; = n
  phi (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; m) = s m

&lt;span class=&quot;hljs-type&quot;&gt;Multiplication&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; a catamorphism:

&lt;span class=&quot;hljs-title&quot;&gt;times&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;times&lt;/span&gt; n = cata phi &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; = z
  phi (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; m) = plus n m

&lt;span class=&quot;hljs-title&quot;&gt;z&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;z&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;mendler-style&quot;&gt;Mendler Style&lt;/h2&gt;
&lt;p&gt;A somewhat less common variation on the theme of a catamorphism is a catamorphism as a recursion scheme a la Mendler, which removes the dependency on the underlying type being an instance of Haskell's Functor typeclass &lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[6]&lt;/a&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MendlerAlgebra&lt;/span&gt; f c = forall a. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) -&amp;gt; f a -&amp;gt; c&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;mcata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;MendlerAlgebra&lt;/span&gt; f c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;mcata&lt;/span&gt; phi = phi (mcata phi) . outF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From that we can derive the original notion of a catamorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; phi = mcata (\f -&amp;gt; phi . fmap f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be seen to be equivalent to the original definition of cata by expanding the definition of &lt;code&gt;mcata&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The principal advantage of using Mendler-style is it is independent of the definition of the &lt;code&gt;Functor&lt;/code&gt; definition for &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;mendler-and-the-yoneda-lemma&quot;&gt;Mendler and the Yoneda Lemma&lt;/h2&gt;
&lt;p&gt;The definition of a Mendler-style algebra above can be seen as the application of the Yoneda lemma to the functor in question.&lt;/p&gt;
&lt;p&gt;In type theoretic terms, the Yoneda lemma states that there is an isomorphism between &lt;code&gt;(f a)&lt;/code&gt; and &lt;code&gt;∃b. (b -&amp;gt; a, f b)&lt;/code&gt;, which can be witnessed by the following definitions.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f a = forall b. &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;toCoYoneda&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;toCoYoneda&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; id

&lt;span class=&quot;hljs-title&quot;&gt;fromCoYoneda&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;fromCoYoneda&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f v) = fmap f v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that in Haskell using an existential requires the use of &lt;code&gt;data&lt;/code&gt;, so there is an extra bottom that can inhabit this type that prevents this from being a true isomorphism.&lt;/p&gt;
&lt;p&gt;However, when used in the context of a &lt;code&gt;(CoYoneda f)&lt;/code&gt;-Algebra, we can rewrite this to use universal quantification because the functor f only occurs in negative position, eliminating the spurious bottom.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f) a
= (by definition)           &lt;span class=&quot;hljs-type&quot;&gt;CoYoneda&lt;/span&gt; f a -&amp;gt; a
~ (by definition)           (exists b. (b -&amp;gt; a, f b)) -&amp;gt; a
~ (lifting the existential) &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. (b -&amp;gt; a, f b) -&amp;gt; a
~ (by currying)             &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. (b -&amp;gt; a) -&amp;gt; f b -&amp;gt; a
= (by definition)           &lt;span class=&quot;hljs-type&quot;&gt;MendlerAlgebra&lt;/span&gt; f a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;generalized-catamorphisms&quot;&gt;Generalized Catamorphisms&lt;/h2&gt;
&lt;p&gt;Most more advanced recursion schemes for folding structures, such as paramorphisms and zygomorphisms can be seen in a common framework as &quot;generalized&quot; catamorphisms&lt;span&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/#references&quot;&gt;[7]&lt;/a&gt;&lt;/span&gt;. A generalized catamorphism is defined in terms of an F-W-algebra and a distributive law for the comonad W over the functor F which preserves the structure of the comonad W.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dist&lt;/span&gt; f w = forall a. f (&lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; w (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FWAlgebra&lt;/span&gt; f w a = f (&lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt;
          &lt;span class=&quot;hljs-type&quot;&gt;Dist&lt;/span&gt; f w -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FWAlgebra&lt;/span&gt; f w a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; k g = extract . c &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  c = liftW g . k . fmap (duplicate . c) . outF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, a generalized catamorphism can be shown to add no more expressive power to the concept of a catamorphism. That said the separation of a number of the &quot;book keeping&quot; concerns by isolating them in a reusable distributive law can ease the development of F-W-algebras.&lt;/p&gt;
&lt;p&gt;We can transform an F-W-algebra into an F-algebra by including the comonad in the carrier for the algebra and then extracting after we perform this somewhat more stylized catamorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lowerAlgebra&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt;
                &lt;span class=&quot;hljs-type&quot;&gt;Dist&lt;/span&gt; f w -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FWAlgebra&lt;/span&gt; f w a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (w a)
&lt;span class=&quot;hljs-title&quot;&gt;lowerAlgebra&lt;/span&gt; k phi = liftW phi . k . fmap duplicate

&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt;
          &lt;span class=&quot;hljs-type&quot;&gt;Dist&lt;/span&gt; f w -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FWAlgebra&lt;/span&gt; f w a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; k phi = extract . cata (lowerAlgebra k phi)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can trivially transform an Algebra into an F-W-Algebra by mapping the counit of the comonad over F. Then using the trivial identity functor, we can represent every catamorphism as a generalized-catamorphism.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;liftAlgebra&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt;
               &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FWAlgebra&lt;/span&gt; f w a

&lt;span class=&quot;hljs-title&quot;&gt;liftAlgebra&lt;/span&gt; phi = phi . fmap extract

&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f = g_cata (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; . fmap runIdentity) (liftAlgebra f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Between these two definitions we can see that a generalized catamorphism does not increase the scope of a catamorphism to encompass any more operations, it simply further stylizes the pattern of recursion.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ol id=&quot;refs&quot;&gt;&lt;li&gt;L. Meertens. First Steps towards the theory of Rose Trees. Draft Report, CWI, Amsterdam, 1987.
&lt;br&gt;
&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/&quot;&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;G. Malcolm. PhD. Thesis. University of Gronigen, 1990.
&lt;br&gt;
&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/&quot;&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;G. Malcolm. Data structures and program transformation. Science of Computer Programming, 14:255--279, 1990.
&lt;br&gt;
&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/&quot;&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;E. Meijer. Calculating Compilers, Ph.D Thesis, Utrecht State University, 1992.
&lt;br&gt;
&lt;a href=&quot;http://research.microsoft.com/~emeijer/Papers/Thesis.pdf&quot;&gt;http://research.microsoft.com/~emeijer/Papers/Thesis.pdf&lt;/a&gt;&lt;/li&gt; &lt;li&gt;E. Meijer, M. Fokkinga, R. Paterson, Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire, 5th ACM Conference on Functional Programming Languages and Computer Architecture.
&lt;br&gt;
&lt;a href=&quot;http://research.microsoft.com/~emeijer/Papers/fpca91.pdf&quot;&gt;http://research.microsoft.com/~emeijer/Papers/fpca91.pdf&lt;/a&gt;&lt;/li&gt; &lt;li&gt;T. Uustalu, V. Vene. Coding Recursion a la Mendler. Proceedings 2nd Workshop on Generic Programming, WGP'2000, Ponte de Lima, Portugal, 6 July 2000
&lt;br&gt;
&lt;a href=&quot;http://citeseer.ist.psu.edu/314266.html&quot;&gt;http://citeseer.ist.psu.edu/314266.html&lt;/a&gt;&lt;/li&gt; &lt;li&gt;T. Uustalu, V. Vene, A. Pardo. Recursion schemes from Comonads. Nordic Journal of Computing. Volume 8 ,  Issue 3  (Fall 2001). 366--390, 2001 ISSN:1236-6064
&lt;br&gt;
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/recursion-schemes-catamorphisms/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Stop Treading Water: Learning to Learn</title><link>https://comonad.com/reader/talks/kmett-2014-stop-treading-water/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2014-stop-treading-water/</guid><category>Talk</category><description>&lt;p&gt;Edward Kmett · 2014 · day unknown&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;j0XmixCsWjs&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=j0XmixCsWjs&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p class=&quot;editorial&quot;&gt;YOW! 2014. This surviving recording is an unofficial mirror uploaded by Adam Piper in 2017; the original organizer-linked video is unavailable.&lt;/p&gt;&lt;p&gt;Stop Treading Water: Learning to Learn — YOW!2014.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Z8KcCU-p8QA&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://yow.eventer.com/yow-2014-1222/stop-treading-water-learning-to-learn-by-edward-kmett-1750&quot;&gt;video historical&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://slides.yowconference.com/yow2014/Kmett-StopTreadingWater.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=j0XmixCsWjs&quot;&gt;video mirror&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2014-stop-treading-water/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>PHOAS For Free</title><link>https://comonad.com/reader/2013/phoas/</link><guid isPermaLink="false">https://comonad.com/reader/2013/phoas/</guid><pubDate>Mon, 09 Dec 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 9 December 2013&lt;/p&gt;&lt;p&gt;Back in 2008 I wrote an article entitled &lt;a href=&quot;https://comonad.com/reader/2008/rotten-bananas/&quot;&gt;&quot;Rotten Bananas&quot;&lt;/a&gt; about how to convert between the different forms of catamorphisms over &quot;exponential&quot; data types that arise when we go to work with Higher Order Abstract Syntax (HOAS).&lt;/p&gt;
&lt;p&gt;Today I want to go back and revisit that post in light of my current understanding of profunctors from working on &lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My goal today is to go through and reformulate Parametric HOAS slightly differently by using profunctors to tease apart the positive and negative occurences of the type variable.&lt;/p&gt;
&lt;p&gt;By doing so, we can show the connection between Fegaras and Sheard's catamorphism and the free monad that laid so close to the surface in the original formulation, and we can derive a variant on Weirich and Washburn's efficient catamorphism by using an alternate encoding of the free monad that I've already &lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less-2/&quot;&gt;blogged about before&lt;/a&gt; in my series on &lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less/&quot;&gt;&quot;Free Monads for Less&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;folding-invariants&quot;&gt;Folding Invariants&lt;/h2&gt;
&lt;p&gt;If we take the base functor for an expression type that has both positive and negative occurences of a variable, there isn't much we can do with our standard tools. It isn't even a &lt;code&gt;Functor&lt;/code&gt;, so it can't be &lt;code&gt;Foldable&lt;/code&gt; or &lt;code&gt;Traversable&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt; or a &lt;code&gt;Monad&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a a
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (a -&amp;gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To work with it, you can define a rather unsatisfying&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  invmap :: (a -&amp;gt; b) -&amp;gt; (b -&amp;gt; a) -&amp;gt; f a -&amp;gt; f b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  invmap ab ba (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y) = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (ab x) (ab y)
  invmap ab ba (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; aa)  = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (ab.aa.ba)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I described this in my 2008 post as &lt;code&gt;ExpFunctor&lt;/code&gt;, based on a similar operation in Weirich and Washburn. It is packaged up in the &lt;code&gt;invariant&lt;/code&gt; package on Hackage as &lt;code&gt;Invariant&lt;/code&gt;, with a method named &lt;code&gt;invmap&lt;/code&gt;, if you find you  really want to use it.&lt;/p&gt;
&lt;p&gt;One of my goals today is to show that we can get away without it!&lt;/p&gt;
&lt;p&gt;Erik Meijer and Graham Hutton showed in &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.64.4921&amp;rep=rep1&amp;type=pdf&quot;&gt;&quot;Bananas in Space&quot;&lt;/a&gt; that you can define a catamorphism over that data type if you can &lt;em&gt;also&lt;/em&gt; define a corresponding anamorphism that serves as its inverse. E.g. to define a pretty printer for this type with Meijer/Hutton's catamorphism you also need a parser. ಠ__ಠ&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;out&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f g (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; x) = f (invmap (cata f g) (ana f g) x)

&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; f g x = &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (invmap (ana f g) (cata f g) (g x))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.2763&quot;&gt;Fegaras and Sheard&lt;/a&gt; showed that if you change the domain of the problem a bit, you can get away with a 'fake' anamorphism, by adding a constructor that you agree never to use, because the anamorphism is only ever used as a right inverse to our catamorphism. They then proceeded to provide a type system for checking this. Adopting the notation from Weirich and Washburn's take on Fegaras and Sheard's catamorphism, this would be:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = f (invmap (cata f) &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; x)
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; x) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can clearly see that &lt;code&gt;Place&lt;/code&gt; forms a right inverse of &lt;code&gt;cata f&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f . &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; = id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can define smart constructors for the running &lt;code&gt;Exp&lt;/code&gt; example, using &lt;code&gt;Roll&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; x y = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Weirich and Washburn noted that you can prevent the accidental use of the type parameter &lt;code&gt;a&lt;/code&gt; by quantifying over it.&lt;/p&gt;
&lt;p&gt;Finally, Weirich and Washburn reimplemented &lt;code&gt;Rec&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a = (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This made &lt;code&gt;cata&lt;/code&gt; ridiculously simple:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: (f a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f x = x f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we don't have &lt;code&gt;Roll&lt;/code&gt; any more, so we need to move the complexity into an explicit &lt;code&gt;roll&lt;/code&gt; combinator:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;roll&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Invariant&lt;/span&gt; f =&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;roll&lt;/span&gt; x f = f (invmap (cata f) place x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We no longer have &lt;code&gt;Place&lt;/code&gt; either, but nothing says &lt;code&gt;(f a -&amp;gt; a) -&amp;gt; a&lt;/code&gt; has to use the supplied function, when we know &lt;code&gt;a&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;place&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;place&lt;/span&gt; = const
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can see:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt; a&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; f = roll (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; x y = roll (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y)

&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; = place
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, in particular in both the Fegaras-Sheard and Weirich-Washburn forms, you can denote a closed term safely using&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ClosedExp&lt;/span&gt; = forall x. &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The safety of this is really the subject of the &quot;Boxes Go Bananas&quot; paper.&lt;/p&gt;
&lt;p&gt;Based on the observations about the price of substitution into free monads by &lt;a href=&quot;http://www.iai.uni-bonn.de/~jv/mpc08.pdf&quot;&gt;Janis Voigtländer&lt;/a&gt;, one should probably favor Weirich and Washburn's construction if you're going to be doing substitution on your HOAS representation -- and if you're not doing substitution, then why are you using HOAS in the first place?!&lt;/p&gt;
&lt;h2 id=&quot;weak-hoas&quot;&gt;Weak HOAS&lt;/h2&gt;
&lt;p&gt;Everything I've mentioned above is a &quot;strong&quot; HOAS variants. You can perform substitution just by passing in the expression you want.&lt;/p&gt;
&lt;p&gt;In weak HOAS (and PHOAS) the decision is made to deal with negative occurences differently than in what we've done so far.&lt;/p&gt;
&lt;p&gt;Instead of taking a full &lt;code&gt;Exp a&lt;/code&gt; in negative position, we're just going to take an &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Written monolithically, it would look something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then our smart constructors change a bit:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;weakens to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We still have both positive and negative occurences of &lt;code&gt;a&lt;/code&gt;, but we no longer have &lt;code&gt;Exp&lt;/code&gt; occurring in both positive and negative position.&lt;/p&gt;
&lt;p&gt;This is particularly popular in the Coq and Agda communities because it can pass the positivity checker, but unlike strong HOAS can be a bit more painful to work with.&lt;/p&gt;
&lt;h2 id=&quot;parametric-hoas&quot;&gt;Parametric HOAS&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://adam.chlipala.net/&quot;&gt;Adam Chlipala&lt;/a&gt; does a lot of work with Parametric HOAS, which is based on a weak HOAS variant of Weirich and Washburn's &lt;a href=&quot;http://www.seas.upenn.edu/~sweirich/papers/itabox/icfp-published-version.pdf&quot;&gt;Boxes Go Bananas: Encoding Higher-Order Abstract Syntax with
Parametric Polymorphism&lt;/a&gt;, which I talked about in that post. His &lt;a href=&quot;http://ltamer.sourceforge.net/&quot;&gt;Lambda Tamer&lt;/a&gt; is based on this model.&lt;/p&gt;
&lt;p&gt;One issue is that neither of these really gives us a free &lt;code&gt;Monad&lt;/code&gt;, due to the fact that the &lt;code&gt;a&lt;/code&gt; occurs in both positive and negative position and so we can't even derive a &lt;code&gt;Functor&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;Adam's work doesn't really feel this pinch, because in &lt;a href=&quot;http://coq.inria.fr/&quot;&gt;Coq&lt;/a&gt; he can &lt;a href=&quot;http://adam.chlipala.net/papers/PhoasICFP08/PhoasICFP08Talk.pdf&quot;&gt;define custom tactics&lt;/a&gt; for &lt;a href=&quot;http://coq.inria.fr/files/adt-30jun09-bruno-ltac.pdf&quot;&gt;&lt;code&gt;ltac&lt;/code&gt;&lt;/a&gt; to use and you generally don't try to factor out this pattern into a library, but when you switch to &lt;a href=&quot;http://wiki.portal.chalmers.se/agda/pmwiki.php&quot;&gt;Agda&lt;/a&gt; and have to do everything by hand, the lack of common abstractions comes to bite you.&lt;/p&gt;
&lt;h2 id=&quot;p-is-for-profunctor&quot;&gt;P is for Profunctor&lt;/h2&gt;
&lt;p&gt;Dan Piponi wrote a nice article on &lt;a href=&quot;http://blog.sigfpe.com/2011/07/profunctors-in-haskell.html&quot;&gt;Profunctors in Haskell&lt;/a&gt; introducing profunctors to the Haskell community, and they now form the basis of much of &lt;code&gt;lens&lt;/code&gt;. Liyang HU also has a more &lt;a href=&quot;https://www.fpcomplete.com/school/pick-of-the-week/profunctors&quot;&gt;tongue in cheek introduction&lt;/a&gt; here on the School of Haskell that he originally presented back in April at a &lt;a href=&quot;https://comonad.com/reader/2013/japanese-workshop-1/&quot;&gt;benkyoukai&lt;/a&gt; about various libraries of mine in Japan.&lt;/p&gt;
&lt;p&gt;To say something is a &lt;code&gt;Profunctor&lt;/code&gt; in Haskell is just to say it is contravariant in the first argument and covariant in the second.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap :: (a -&amp;gt; b) -&amp;gt; (c -&amp;gt; d) -&amp;gt; p b c -&amp;gt; p a d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This argument order is a bit reversed from how it is usually tackled in category theory, but by lining things up this way we match up with the variances for &lt;code&gt;Arrow&lt;/code&gt; and &lt;code&gt;(-&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For convenience we also provide class methods for:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lmap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (a -&amp;gt; b) -&amp;gt; p b c -&amp;gt; p a c
&lt;span class=&quot;hljs-title&quot;&gt;rmap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (b -&amp;gt; c) -&amp;gt; p a b -&amp;gt; p a c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice when I wrote the Weak HOAS definition, I had to keep it monolithic? To factor out &lt;code&gt;Var&lt;/code&gt; / &lt;code&gt;Place&lt;/code&gt;, it winds up needing two type parameters, since now both &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;Exp a&lt;/code&gt; occur inside the expression.&lt;/p&gt;
&lt;p&gt;So, if we go back to the start and separate positive and negative occurences of these, we're left with something like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt; a b&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; b b
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (a -&amp;gt; b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This forms a valid &lt;code&gt;Profunctor&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y) = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (g x) (g y)
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; h)   = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (g.h.f)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;phoas-is-free&quot;&gt;PHOAS Is Free&lt;/h2&gt;
&lt;p&gt;Now we can revisit the &lt;code&gt;Exp&lt;/code&gt; we were talking about in the section on Weak HOAS and we can rip apart the old:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Var&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Abs&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into the application of a Fegaras and Sheard free-monad-like construction&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; b
  | &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (p a (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to our base profunctor &lt;code&gt;ExpF&lt;/code&gt;, so now&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpF&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now, we're no longer free-monad like, we're actually a free monad!&lt;/p&gt;
&lt;p&gt;We can even define this &lt;code&gt;Monad&lt;/code&gt;, by cribbing the definition from &lt;a href=&quot;https://hackage.haskell.org/package/free&quot;&gt;&lt;code&gt;free&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; b  &amp;gt;&amp;gt;= f = f b
  &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; bs &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; $ rmap (&amp;gt;&amp;gt;= f) bs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &lt;code&gt;Monad&lt;/code&gt; even performs capture avoiding substitution.&lt;/p&gt;
&lt;p&gt;The Fegaras-Sheard catamorphism doesn't change much&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (p a b -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; phi (&lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; b)  = b
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; phi (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; bs) = phi (rmap (cata phi) bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, it now just turns a &lt;code&gt;p a&lt;/code&gt;-algebra into a &lt;code&gt;Rec p a&lt;/code&gt;-algebra, and doesn't need to use &lt;code&gt;Place&lt;/code&gt; at all!&lt;/p&gt;
&lt;p&gt;And we get weak HOAS style smart constructors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; x y = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;var&lt;/code&gt; is the only thing that &lt;a href=&quot;http://www.youtube.com/watch?v=jyaLZHiJJnE&quot;&gt;crosses the streams&lt;/a&gt; and causes the two type arguments to unify&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; :: b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; = return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice the difference between the type of the argument of &lt;code&gt;lam&lt;/code&gt; and the signature of &lt;code&gt;var&lt;/code&gt;. This causes actual expressions that use any variable they bind to wind up with the types agreeing:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a a
&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; = lam $ \x -&amp;gt; lam $ \y -&amp;gt; app (var x) (var y)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;take-the-end&quot;&gt;Take The End&lt;/h2&gt;
&lt;p&gt;Now instead of talking about a closed term in terms of quantifying over a single parameter that can only vary with an isomorphism, we take an end over our &lt;code&gt;Profunctor&lt;/code&gt; instead:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; p = forall x. p x x&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;iter0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (p a a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;iter0&lt;/span&gt; phi x = cata phi x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I intend to write up a post on how to &quot;read&quot; universal properties as types, to help folks see where this definition for &lt;code&gt;End&lt;/code&gt; comes from.&lt;/p&gt;
&lt;p&gt;This was the Free monad I just said you probably don't want to use for substitution, so let's go try the other one.&lt;/p&gt;
&lt;h2 id=&quot;boxes-go-bananas-for-less&quot;&gt;Boxes Go Bananas For Less&lt;/h2&gt;
&lt;p&gt;Recall Weirich and Washburn's &lt;code&gt;Rec&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a = (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we go to turn that into a &lt;code&gt;Profunctor&lt;/code&gt; directly we get stuck.&lt;/p&gt;
&lt;p&gt;We could make&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runRec&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and get the variances right for a &lt;code&gt;Profunctor&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; h) = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; $ \pab2a -&amp;gt; g $ h $ f . pab2a . dimap f g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this doesn't look much like the instance I derived from Fegaras and Sheard's construction, and doesn't give us a Monad!&lt;/p&gt;
&lt;p&gt;They could pull this off because &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; were interchangeable in either direction. We're a bit more constrained.&lt;/p&gt;
&lt;p&gt;We could turn to &lt;code&gt;Codensity&lt;/code&gt; of my weak variant of the Fegaras-Sheard construction, but as I've blogged about before, &lt;code&gt;Codensity (Free f)&lt;/code&gt; is bigger than it needs to be.&lt;/p&gt;
&lt;p&gt;Fortunately, that same series ended showing how you can get there with just Yoneda. Armed with that, we can borrow the Church-Free monad and get a Weirich and Wasburn-style &lt;code&gt;Profunctor&lt;/code&gt; for &lt;code&gt;Rec&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt;&lt;/span&gt;
  { runRec :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r.
    (b -&amp;gt; r) -&amp;gt; (p a r -&amp;gt; r) -&amp;gt; r
  }
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g m = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; $ \kp kf -&amp;gt; runRec m (kp.g) (kf.lmap f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We retain the &lt;code&gt;Monad&lt;/code&gt; we won by splitting our type parameters in the weak Fegaras-Sheard variant above:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return b = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; $ \ br _ -&amp;gt; br b
  m &amp;gt;&amp;gt;= f  = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; $ \kp kf -&amp;gt;
    runRec m (\a -&amp;gt; runRec (f a) kp kf) kf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can define the rest of the catamorphism machinery:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; p = forall x. p x x&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (p a b -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; phi m = runRec m id phi

&lt;span class=&quot;hljs-title&quot;&gt;roll&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; p a (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p a b
&lt;span class=&quot;hljs-title&quot;&gt;roll&lt;/span&gt; w = &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; $ \kp kf -&amp;gt; kf (rmap (\r -&amp;gt; runRec r kp kf) w)

&lt;span class=&quot;hljs-title&quot;&gt;iter0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; p =&amp;gt; (p a a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; p) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;iter0&lt;/span&gt; phi x = cata phi x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can put together our smart constructors&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; f = roll (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; x y = roll (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; x y)

&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; :: b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;var&lt;/span&gt; = return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can build expressions&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; a a
&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; = lam $ \x -&amp;gt; lam $ \y -&amp;gt; app (var x) (var y)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There is a lot more we can play with here.&lt;/p&gt;
&lt;p&gt;Many expression types will admit a &lt;code&gt;Strong&lt;/code&gt; instance. Now that we've split the input and output parameters can we perhaps use that or something like it to more easily &lt;a href=&quot;http://www.haskell.org/pipermail/haskell-cafe/2008-November/049473.html&quot;&gt;manipulate environments&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Just like with &lt;a href=&quot;https://comonad.com/reader/2015/bound/&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; we can build an &lt;a href=&quot;http://github.com/ekmett/indexed&quot;&gt;&lt;code&gt;indexed&lt;/code&gt;&lt;/a&gt; version of this construction that permits us to write strongly typed EDSLs. That is how PHOAS is usually presented in Coq after all.&lt;/p&gt;
&lt;p&gt;There is also probably a lot more to be said about dinaturality here.&lt;/p&gt;
&lt;p&gt;I still generally prefer working with &lt;a href=&quot;https://hackage.haskell.org/package/bound&quot;&gt;&lt;code&gt;bound&lt;/code&gt;&lt;/a&gt; to working in HOAS these days, because it is much easier to work under lambdas, and it is easier to grab all your free variables using &lt;code&gt;Foldable&lt;/code&gt; and &lt;code&gt;Traversable&lt;/code&gt; and harder to make mistakes with.&lt;/p&gt;
&lt;p&gt;That said it is good to finally be able to merge together the notion of Fegaras and Sheard's construction and the standard free monad.&lt;/p&gt;
&lt;p&gt;This also strikes me as a good first step towards being able to turn PHOAS into something that can be encoded usefully in Haskell as a library rather than a design pattern.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://plus.google.com/u/0/113063331545548237308?rel=author&quot;&gt;-&lt;/a&gt;[-](&lt;a href=&quot;https://plus.google.com/u/0/113063331545548237308&quot; rel=&quot;publisher&quot;&gt;-&lt;/a&gt;)&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 18th, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/phoas/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cache-Oblivious Data Structures — Part I: Deamortized ST</title><link>https://comonad.com/reader/2013/oblivious-deamortized-st/</link><guid isPermaLink="false">https://comonad.com/reader/2013/oblivious-deamortized-st/</guid><pubDate>Fri, 08 Nov 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 8 November 2013&lt;/p&gt;&lt;p&gt;A week or two ago I gave a talk at Mozilla, San Francisco on &lt;a href=&quot;http://www.youtube.com/watch?v=P3pLDpbzqCw&quot;&gt;Cache-Oblivious Maps&lt;/a&gt; to the Bay Area Haskell User Group.&lt;/p&gt;
&lt;p&gt;My goal with this series of posts is to ultimately improve on the conclusion of that talk to generate a purely functional version of a structure like &lt;a href=&quot;http://supertech.csail.mit.edu/papers/sbtree.pdf&quot;&gt;Bender &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt;'s cache-oblivious lookahead array and the &lt;a href=&quot;http://arxiv.org/pdf/1103.4282v2.pdf&quot;&gt;stratified B-tree&lt;/a&gt;, closing the gap between the performance of imperative and functional data structures in this space.&lt;/p&gt;
&lt;p&gt;In short I want a really fast &lt;code&gt;Map&lt;/code&gt;, optimized for contiguous use of memory that hits provably optimal asymptotics across the board for a wide array of problems despite exposing a purely functional API.&lt;/p&gt;
&lt;p&gt;We won't get there today, but we'll at least establish some of the building blocks.&lt;/p&gt;
&lt;p&gt;Today, I want to talk about a new trick that I came up with that allows us work with observably-functional algorithms in Haskell that can provide them with a purely-functional API in the same manner as the &lt;code&gt;ST&lt;/code&gt; monad does today, but which permits us enough additional control over scheduling that we can deamortize many such algorithms.&lt;/p&gt;
&lt;h2 id=&quot;the-price-of-purity&quot;&gt;The Price of Purity&lt;/h2&gt;
&lt;p&gt;In a purely functional language, &lt;a href=&quot;http://en.wikipedia.org/wiki/Amortized_analysis&quot;&gt;amortized analysis&lt;/a&gt; is further hampered by the fact that every previous version of a structure is available at all times, so you have to consider that any structure can participate in multiple futures. This makes working with amortization much trickier.&lt;/p&gt;
&lt;p&gt;You can't really earn credit by doing things cheaply and then use all that credit to do something big later depending on data not known when you earned the credit because someone may reuse the data structure with different data, and respend the same credit!&lt;/p&gt;
&lt;p&gt;In a purely-functional setting, if you don't use your budget this time you won't get more to spend later. It is just gone!&lt;/p&gt;
&lt;p&gt;The trick is coming up with the right contortions, so that you can build in enough lag in your data structures to ensure that you always have just enough to work on.&lt;/p&gt;
&lt;h2 id=&quot;the-price-of-laziness&quot;&gt;The Price of Laziness&lt;/h2&gt;
&lt;p&gt;Chris Okasaki's book &lt;a href=&quot;http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504&quot;&gt;Purely Functional Data Structures&lt;/a&gt; and &lt;a href=&quot;http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf&quot;&gt;thesis&lt;/a&gt; cover a suite of tools for reasoning about asymptotics in a pure &lt;em&gt;lazy&lt;/em&gt; language.&lt;/p&gt;
&lt;p&gt;He notes that you can often set up a thunk that will evaluate to the right result, if you know all the data you'll need to calculate its answer in the end. Then if two versions of the data structure in the future force this same thunk then they'll share the answer, but only compute it once. This preserves the correctness of the asymptotic analysis of the algorithm despite amortization.&lt;/p&gt;
&lt;p&gt;We get quite a bit more flexibility with regards to amortization than in the strict setting. Now we can pay into an account for later by building a thunk we'll force in later calculations.&lt;/p&gt;
&lt;h2 id=&quot;slowdown-what-is-the-worst-case&quot;&gt;Slowdown: What is the Worst Case?&lt;/h2&gt;
&lt;p&gt;When amortized complexity bounds aren't enough you can often follow Okasaki's advice and use even more advanced techniques such as &quot;Implicit Recursive Slowdown&quot;, a variant on a technique by Kaplan and Tarjan.  There we set up a series of thunks you'll evaluate over time, each individually relatively cheap, so that you can turn amortized bounds into worst case bounds. Then you just force an appropriate amount of work as you go.&lt;/p&gt;
&lt;p&gt;By setting up the thunks and paying them down by forcing them at just the right time you can often derive quite good worst-case performance in a purely functional persistent setting, so long as you have access to laziness.&lt;/p&gt;
&lt;p&gt;There are still some algorthms such as Tarjan's &lt;a href=&quot;http://en.wikipedia.org/wiki/Disjoint-set_data_structure&quot;&gt;Union-Find&lt;/a&gt; problem that don't seem to yield to this technique, but surprisingly many do.&lt;/p&gt;
&lt;h2 id=&quot;partiality-as-an-effect&quot;&gt;Partiality as an Effect&lt;/h2&gt;
&lt;p&gt;So, if I want to set up such a chain of thunks, what would be a good general purpose way to go about it?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://arxiv.org/pdf/cs/0505037v6.pdf&quot;&gt;Venanzio Capretta&lt;/a&gt; defined a simple partiality monad. I'll play with the names a bit and reproduce a version of it here:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (m &amp;gt;&amp;gt;= f)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Those of you who watch out for such things will recognize this as just &lt;code&gt;Free Identity&lt;/code&gt;, though technically there is a distinction to be had when you move beyond Haskell here. This is based on &lt;code&gt;νx. a + x&lt;/code&gt; rather than &lt;code&gt;μx. a + x&lt;/code&gt;, but in Haskell, &lt;code&gt;ν&lt;/code&gt; and &lt;code&gt;μ&lt;/code&gt; coincide. This means that technically we're using the &quot;completely iterative&quot; monad based on &lt;code&gt;Identity&lt;/code&gt;, not the free construction, but I digress.&lt;/p&gt;
&lt;p&gt;Using it you can run a calculation a number of steps and check to see if it has stopped with an answer yet.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; m = m
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; n m@&lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt;{} = m
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; n (&lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; m) = run (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can inject steps into a calculation to demarcate time.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (return ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a trivial example, you can also define a calculation that no matter how many steps you take will spin forever, but where each individual &lt;code&gt;Step&lt;/code&gt; takes &lt;em&gt;O(1)&lt;/em&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;never&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;never&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; never
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using this if you have a purely functional algorithm that builds a sub-structure gradually you could pay it down &lt;code&gt;Step&lt;/code&gt; by &lt;code&gt;Step&lt;/code&gt; by burying a &lt;code&gt;Partial&lt;/code&gt; result somewhere down in your structure. If you are careful about the amount of work within a &lt;code&gt;Step&lt;/code&gt; then you can reason about the asymptotics of the overall system.&lt;/p&gt;
&lt;h2 id=&quot;the-power-of-mutation&quot;&gt;The Power of Mutation&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img alt=&quot;Illustration from Cache-Oblivious Data Structures — Part I: Deamortized ST&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/a72ad9ec6493-x-men.jpg&quot; style=&quot;padding-bottom: 10px&quot;&gt;&lt;/div&gt;
&lt;p&gt;There is an old result by &lt;a href=&quot;http://www.cs.princeton.edu/courses/archive/fall03/cs528/handouts/Pure%20Versus%20Impure%20LISP.pdf&quot;&gt;Pippenger&lt;/a&gt; that showed that an algorithm implemented in a pure strict language may need to suffer a logarithmic slowdown relative to an algorithm implemented in a strict language with side-effects.&lt;/p&gt;
&lt;p&gt;The fact that the slowdown for some algorithms is at least logarithmic in the absence of mutation can be shown using a fairly easy pigeon-hole argument.&lt;/p&gt;
&lt;p&gt;The fact that the slowdown is at most logarithmic derives from the fact that you could always maintain a set of 'references' yourself in a &lt;code&gt;Map&lt;/code&gt; like structure, in exchange for logarithmic overhead on (de)reference.&lt;/p&gt;
&lt;p&gt;The price you pay for this power is that mutation brings with it its own headaches. From a free theorem perspective every mutable input is now effectively an extra output, and you have all sorts of spooky action at a distance concerns entangling distant parts of your program.&lt;/p&gt;
&lt;h2 id=&quot;laziness-is-its-own-reward&quot;&gt;Laziness is its Own Reward&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img alt=&quot;Illustration from Cache-Oblivious Data Structures — Part I: Deamortized ST&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/76b8edd11c9f-jennifer-lawrence-pants.gif&quot; style=&quot;padding-bottom: 10px&quot;&gt;&lt;/div&gt;
&lt;p&gt;Pippenger's analysis relied on the absence of mutation.&lt;/p&gt;
&lt;p&gt;In a non-strict language like Haskell, graph reduction / memoization of thunk evaluation provides us with a limited form of mutation! This renders his analysis inconclusive.&lt;/p&gt;
&lt;p&gt;Many algorithms that are provably slowed down asymptotically in a strict pure language can be implemented just fine in a non-strict language, by creative contortions to exploit this limited form of mutation.&lt;/p&gt;
&lt;p&gt;This means we can at least sometimes win a log factor in a strict setting by cheating and using side-effects. There may or may not be cases where we need to pay an extra logarithmic factor for this in a lazy functional setting, but we don't have a definitive proof one way or the other.&lt;/p&gt;
&lt;p&gt;My goal today is to help narrow the gap a bit by cheating.&lt;/p&gt;
&lt;h2 id=&quot;is-it-cheating-if-you-don-t-get-caught&quot;&gt;Is It Cheating If You Don't Get Caught?&lt;/h2&gt;
&lt;p&gt;If your algorithm builds an immutable result, then does it matter how you built it?&lt;/p&gt;
&lt;img alt=&quot;Illustration from Cache-Oblivious Data Structures — Part I: Deamortized ST&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/941d9e644978-cheater.jpg&quot; style=&quot;float: right; width:45%;margin-left:10px; margin-bottom:15px&quot;&gt;
&lt;p&gt;Secretly cheating and doing mutable stuff behind the user's back but only exposing immutable purely functional trappings has been the job of the &lt;code&gt;ST s&lt;/code&gt; monad in Haskell since John Launchbury and Simon Peyton Jones introduced it in &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.144.2237&amp;rep=rep1&amp;type=pdf&quot;&gt;Lazy Functional State Threads&lt;/a&gt; back in 1994.&lt;/p&gt;
&lt;p&gt;The idea behind &lt;code&gt;ST&lt;/code&gt; is that as long as nobody knows that you cheated and nobody can observe that you did, and no matter how many times they try to catch you you get away with it, does it matter that you cheated? I will definitely &lt;em&gt;not&lt;/em&gt; be trying this line of reasoning with my wife, but types are more forgiving.&lt;/p&gt;
&lt;p&gt;I'm not going to dive into the use of the &lt;code&gt;ST s&lt;/code&gt; monad here, beyond noting that it looks a lot like the &lt;code&gt;IO&lt;/code&gt; monad under the hood with a much reduced palette of operations intended so that the result of the &lt;code&gt;ST s&lt;/code&gt; calculation should be deterministic.&lt;/p&gt;
&lt;br clear=&quot;all&quot;&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;newSTRef&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;STRef&lt;/span&gt; s a)
&lt;span class=&quot;hljs-title&quot;&gt;readSTRef&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;STRef&lt;/span&gt; s a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;writeSTRef&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;STRef&lt;/span&gt; s a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s ()
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you're done, you run the entire &lt;code&gt;ST s&lt;/code&gt; calculation at once:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runST&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s. &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s a) -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since you are universally quantified over the choice of &lt;code&gt;s&lt;/code&gt;, you can't use references produced in one &lt;code&gt;ST&lt;/code&gt; calculation in another, and encapsulation, referential transparency and all the good things about functional programming are preserved.&lt;/p&gt;
&lt;p&gt;However, we had to run the entire effect at once.&lt;/p&gt;
&lt;p&gt;If I want to amortize it and pay it down over time, I'm out of luck. In the end I'm interested in building very large vectors but paying for their construction in very small, affordable, chunks.&lt;/p&gt;
&lt;p&gt;That's where today's hackery comes in.&lt;/p&gt;
&lt;h2 id=&quot;every-step-you-take&quot;&gt;Every Step You Take&lt;/h2&gt;
&lt;p&gt;My first thought was of course to use something like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;walkST&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s. &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s) a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;walkST&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s. &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s) a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this has the problem that &lt;a href=&quot;http://www.youtube.com/watch?v=OMOGaugKpzs&amp;t=26s&quot;&gt;every step you take&lt;/a&gt; will be observed and must be paid for, even little administrative actions at the end, such as freezing the result vector costs you an extra step.&lt;/p&gt;
&lt;p&gt;If I want to do something like work with existing &lt;code&gt;Stream&lt;/code&gt; fusion out of &lt;code&gt;vector&lt;/code&gt; and just have it pay once for every &lt;code&gt;step&lt;/code&gt;, this approach isn't going to cut it.&lt;/p&gt;
&lt;p&gt;You could bandaid this with a coproduct and use &lt;code&gt;Free (ST s :+: Identity)&lt;/code&gt; and promise not to use the knowledge that the &lt;code&gt;ST s&lt;/code&gt; calculations were generated separately for evil, but given the amount of time I recently spent talking about &lt;a href=&quot;https://comonad.com/reader/2013/editorial-procrustean-mathematics/&quot;&gt;rightsizing abstractions&lt;/a&gt;, it'd be hypocritical for me not to try to find a better way.&lt;/p&gt;
&lt;h2 id=&quot;capretta-s-iterative-monad-transformer&quot;&gt;Capretta's Iterative Monad Transformer&lt;/h2&gt;
&lt;p&gt;We can upgrade Capretta's partiality monad to a monad transformer as done by &lt;a href=&quot;http://www.ioc.ee/~tarmo/tday-veskisilla/uustalu-slides.pdf&quot;&gt;Capretta, Altenkirch and Uustalu&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m a = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt;&lt;/span&gt;
  { runIterT :: m (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m a))
  }
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; $
    m &amp;gt;&amp;gt;= either (runIterT . k) (return . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; . (&amp;gt;&amp;gt;= k))
  fail = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; . fail

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've added &lt;code&gt;IterT&lt;/code&gt; and its dual to &lt;code&gt;free&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Here we can still insert explicit steps:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m ()
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; . return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you've been playing with free monads for a while you'll recognize this as a version of &lt;code&gt;FreeT Identity m&lt;/code&gt; from the &lt;code&gt;free&lt;/code&gt; package, rather than the simpler &lt;code&gt;Free m&lt;/code&gt; above. Again, we face the technical distinction that this is based on &lt;code&gt;νx. ST s (a + x)&lt;/code&gt; not &lt;code&gt;μx. ST s (a + x)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IterT&lt;/code&gt; has been added to the &lt;code&gt;free&lt;/code&gt; package in version 4.2 as a distinct construction from &lt;code&gt;FreeT Identity&lt;/code&gt; to help drive this distinction home!&lt;/p&gt;
&lt;p&gt;Now what we want to do now is generate a slower version of &lt;code&gt;runST&lt;/code&gt; that takes a properly quantified &lt;code&gt;ST s&lt;/code&gt; calculation with inserted step markers and walks through it carefully, one step at a time:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;walkST&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s. &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s) a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;walking-the-walk&quot;&gt;Walking the Walk&lt;/h2&gt;
&lt;p&gt;We have a few options for how to implement &lt;code&gt;walkST&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is possible to do this entirely with &lt;code&gt;unsafeInterleaveST&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is actually a non-trivial exercise and it is very easy to accidentally write a version that is too eager and performs effects too soon. My best version so far requires two uses of &lt;code&gt;unsafeInterleaveST&lt;/code&gt; to get the right semantics.&lt;/p&gt;
&lt;p&gt;I leave this as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;You can also rummage through &lt;a href=&quot;http://lpaste.net/&quot;&gt;λpaste&lt;/a&gt; for old versions of this monad for tips. ;)&lt;/p&gt;
&lt;h2 id=&quot;newsflash-unsafeinterleavest-is-unsafe&quot;&gt;Newsflash: &lt;code&gt;unsafeInterleaveST&lt;/code&gt; Is Unsafe!&lt;/h2&gt;
&lt;p&gt;Even if you get that right though, &lt;code&gt;unsafeInterleaveST&lt;/code&gt; is a whole lot more unsafe for this use case, than the equivalent &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; operation! To understand why we need to look down in the guts of each of them.&lt;/p&gt;
&lt;p&gt;When a thunk is evaluated in GHC there is an ever so tiny race condition. When one thread enters into a thunk there is a tiny 1-2 cycle window between that thread entering and establishing the &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?rep=rep1&amp;type=pdf&amp;doi=10.1.1.125.857&quot;&gt;greyhole&lt;/a&gt; that will catch other threads and make them block, during which another thread could come along and start evaluating the same thunk at the same time.&lt;/p&gt;
&lt;p&gt;In the absence of side-effects this is benign. The risk is so low relative to the astronomical costs of synchronization across threads that we, well, just don't bother synchronizing.&lt;/p&gt;
&lt;p&gt;This of course would be bad if the thunk &lt;em&gt;did&lt;/em&gt; have side-effects, &lt;em&gt;e.g.&lt;/em&gt; if it called &lt;code&gt;unsafePerformIO&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Internally &lt;code&gt;unsafePerformIO&lt;/code&gt; calls &lt;code&gt;noDuplicate&lt;/code&gt; to check to make sure that we're not duplicating effort and effects:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsafePerformIO&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unsafePerformIO&lt;/span&gt; m = unsafeDupablePerformIO (noDuplicate &amp;gt;&amp;gt; m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly &lt;code&gt;unsafeInterleaveIO&lt;/code&gt; also checks &lt;code&gt;noDuplicate&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveIO&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveIO&lt;/span&gt; m = unsafeDupableInterleaveIO (noDuplicate &amp;gt;&amp;gt; m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But &lt;code&gt;unsafeInterleaveST&lt;/code&gt;, on the other hand rather boldly does not.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveST&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;unsafeInterleaveST&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; ( \ s -&amp;gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
        r = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; (# _, res #) -&amp;gt; res
    &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt;
    (# s, r #)
  )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that it may very well wind up duplicating work if the result &lt;code&gt;r&lt;/code&gt; of the &lt;code&gt;ST s a&lt;/code&gt; calculation we called &lt;code&gt;unsafeInterleaveST&lt;/code&gt; on is evaluated via &lt;code&gt;par&lt;/code&gt;. And since we don't control what users will do with our code, you really do need to allow for that.&lt;/p&gt;
&lt;p&gt;Roman Leschinskiy's cute &lt;a href=&quot;http://unlines.wordpress.com/2010/04/21/sparking-imperatives/&quot;&gt;Sparking Imperatives&lt;/a&gt; hack even mixes &lt;code&gt;par&lt;/code&gt; with &lt;code&gt;ST&lt;/code&gt;, but he is careful to &lt;code&gt;noDuplicate&lt;/code&gt; as he goes.&lt;/p&gt;
&lt;p&gt;Now, there is possibly a very good reason for this distinction. If we look at the haddocks for &lt;code&gt;noDuplicate&lt;/code&gt; it&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ensures that the suspensions under evaluation by the current thread
are unique; that is, the current thread is not evaluating anything
that is also under evaluation by another thread that has also executed
'noDuplicate'.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So we're faced with a dilemma (trilemma?), we can either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;abandon the use of &lt;code&gt;unsafeInterleaveST&lt;/code&gt; entirely as too risky.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reason through whether &lt;code&gt;noDuplicate&lt;/code&gt; would be legal to use and how to mix it with the existing &lt;code&gt;unsafeInterleaveST&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;or we can require the end user to only ever perform idempotent operations in the &lt;code&gt;ST&lt;/code&gt; monad!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For now I'm largely restricting myself to #1 and #3.&lt;/p&gt;
&lt;p&gt;For an API I expect to expose to an end user, I'm most likely to choose option #1. Anything they do with the resulting construction can be branded &lt;code&gt;Trustworthy&lt;/code&gt; and they don't need to know how it is built in too much detail.&lt;/p&gt;
&lt;p&gt;But when I'm writing code myself that merely exposes a pure façade, the performance benefits of #3 may well outweigh the reasoning difficulties. In principle, if my principal operations are merging elements from two immutable input vectors and generating output in another vector, so long as I'm not bumping a counter stored in an &lt;code&gt;STRef&lt;/code&gt;, everything I do will have idempotent effects.&lt;/p&gt;
&lt;p&gt;In the long term, it is probably worth checking to see if &lt;code&gt;unsafeInterleaveST&lt;/code&gt; should be updated to do &lt;code&gt;noDuplicate&lt;/code&gt; and thereby close out the concern about #2, effectively merging it performance-wise with option #1.&lt;/p&gt;
&lt;p&gt;This still leaves option #3 open for constant tuning in the same crazy way as the &lt;code&gt;inlinePerformIO&lt;/code&gt; hackery gets used down in &lt;code&gt;bytestring&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-safer-alternative-unsafeperformio&quot;&gt;A Safer Alternative: &lt;code&gt;unsafePerformIO&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You have to love it when &lt;code&gt;unsafePerformIO&lt;/code&gt; is the safest option.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.ST
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; System.IO.Unsafe &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unsafe
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.ST.Unsafe &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unsafe


&lt;span class=&quot;hljs-title&quot;&gt;walkST&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; s. &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ST&lt;/span&gt; s) a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;walkST&lt;/span&gt; m = go m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go (&lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m) =
    &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Unsafe&lt;/span&gt;.unsafePerformIO $
         &lt;span class=&quot;hljs-type&quot;&gt;Unsafe&lt;/span&gt;.unsafeSTToIO m &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt; a
      &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; m -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (go m)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m a = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt;&lt;/span&gt;
  { runIterT :: m (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m a))
  }
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; . return . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; $
    m &amp;gt;&amp;gt;= either (runIterT . k) (return . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; . (&amp;gt;&amp;gt;= k))
  fail = &lt;span class=&quot;hljs-type&quot;&gt;IterT&lt;/span&gt; . fail

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Partial&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Stop&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
  &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; (m &amp;gt;&amp;gt;= f)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we're relying on the fact that we perform one step at a time, and that we're evaluating an &quot;entirely sealed&quot; &lt;code&gt;ST s&lt;/code&gt; calculation. When we're done and have the answer &lt;code&gt;a&lt;/code&gt; in our &lt;code&gt;Partial a&lt;/code&gt;, like with conventional &lt;code&gt;ST s&lt;/code&gt; we can't go back and use any of our references any more. In &lt;code&gt;walkST&lt;/code&gt; we keep reopening the same ST region, but we only do so after we look around and make sure nobody else is going to catch us and nobody else is doing the same thing.&lt;/p&gt;
&lt;p&gt;With this, we can go through and do things like calculate an &lt;code&gt;n&lt;/code&gt;-element unboxed vector in &lt;code&gt;n&lt;/code&gt; individually worst-case constant time steps!&lt;/p&gt;
&lt;h2 id=&quot;next-time&quot;&gt;Next Time&lt;/h2&gt;
&lt;p&gt;This opens up new opportunities for matching worst case asymptotic bounds of algorithms from the imperative world in a purely functional setting.&lt;/p&gt;
&lt;p&gt;Next time I'll start to explore how we can mix this approach with a novel (to me) choice of number system to dynamize and deamortize large immutable lookup structures.&lt;/p&gt;
&lt;p&gt;Happy Halloween!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;
Oct 31, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/oblivious-deamortized-st/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Procrustean Mathematics</title><link>https://comonad.com/reader/2013/editorial-procrustean-mathematics/</link><guid isPermaLink="false">https://comonad.com/reader/2013/editorial-procrustean-mathematics/</guid><pubDate>Fri, 08 Nov 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 8 November 2013&lt;/p&gt;&lt;p&gt;This post is a bit of a divergence from my norm.&lt;/p&gt;
&lt;p&gt;I'm going to editorialize a bit about mathematics, type classes and the tension between different ways of fitting ideas together, rather than about any one algorithm or data structure.&lt;/p&gt;
&lt;p&gt;I apologize in advance for the fact that my examples are written from my perspective, and as I'm writing about them unilaterally my characterization is likely to be unfair. Something in here is likely to offend everyone.&lt;/p&gt;
&lt;h2 id=&quot;generalized-abstract-nonsense&quot;&gt;Generalized Abstract Nonsense&lt;/h2&gt;
&lt;p&gt;The term &quot;generalized abstract nonsense&quot; was originally coined by &lt;a href=&quot;http://en.wikipedia.org/wiki/Norman_Steenrod&quot;&gt;Norman Steenrod&lt;/a&gt; as a term of endearment, rather than of denigration. &lt;em&gt;e.g.&lt;/em&gt; Saying in passing &quot;this is true by abstract nonsense&quot; when referring to a long-winded proof that offers no insight into the domain at hand.&lt;/p&gt;
&lt;p&gt;Now, some mathematicians like to refer to category theory as &lt;a href=&quot;http://en.wikipedia.org/wiki/Abstract_nonsense&quot;&gt;&lt;em&gt;generalized abstract nonsense&lt;/em&gt;&lt;/a&gt;, not out of endearment, but because they do not find immediate value in its application. Among category theorists this view is seen as somewhat daft, as they view category theory as a sort of &lt;a href=&quot;http://math.ucr.edu/home/baez/rosetta.pdf&quot;&gt;Rosetta Stone&lt;/a&gt; for mapping ideas from one area of mathematics to another -- a &lt;em&gt;lingua franca&lt;/em&gt; that lets you express commonalities and cross-cutting concerns across domains.&lt;/p&gt;
&lt;p&gt;To me category theory serves as a road map to new domains. I don't know much about &lt;a href=&quot;http://en.wikipedia.org/wiki/Tangle_%28mathematics%29&quot;&gt;rational tangles&lt;/a&gt;, but if I know that with 2 dimensions of freedom, they form a braided monoidal category letting me tie myself in er.. knots, but in 3 or more dimensions they form a symmetric monoidal category, letting me untie all knots.&lt;/p&gt;
&lt;p&gt;With this, I can work with them and derive useful results without caring about irrelevant details and dealing with rope burn.&lt;/p&gt;
&lt;h2 id=&quot;centipede-mathematics&quot;&gt;Centipede Mathematics&lt;/h2&gt;
&lt;p&gt;Just as some general mathematicians look down with various degrees of seriousness upon generalized abstract nonsense, even some category theorists look down upon what the analyst Antoni Zygmund famously referred to as &lt;a href=&quot;http://ncatlab.org/nlab/show/centipede+mathematics&quot;&gt;&lt;em&gt;centipede mathematics&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You take a centipede and pull off ninety-nine of its legs and see what it can do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this sense working with a &lt;code&gt;Semigroup&lt;/code&gt; is just working with a neutered &lt;code&gt;Monoid&lt;/code&gt; that has had its unit removed. The usual critique of &quot;centipede mathematics&quot; is that it lacks taste.&lt;/p&gt;
&lt;p&gt;With such colorful metaphors, it'd be hard to argue otherwise!&lt;/p&gt;
&lt;p&gt;The negative view of this practice seems to stem from the era of folks evaluating grant proposals to see whether or not it was likely to lead to interesting research that they could use. With fewer parts to use, it would seem that one would be unlikely to find new results that benefit those solely concerned with the larger mathematical object.&lt;/p&gt;
&lt;p&gt;But in many ways, all of &lt;a href=&quot;http://en.wikipedia.org/wiki/Abstract_algebra#Modern_algebra&quot;&gt;modern abstract algebra&lt;/a&gt; can be seen as an exercise in centipede mathematics.&lt;/p&gt;
&lt;p&gt;Mathematicians started with the real numbers, which sit on a line, and, coincidentally, with suitable markers, look an awful lot like a centipede. Starting from there at the turn of the last century, mathematicians kept ripping off legs to get fields, rings, groups, monoids, etc.&lt;/p&gt;
&lt;h2 id=&quot;applied-mathematics-and-computer-science&quot;&gt;Applied Mathematics and Computer Science&lt;/h2&gt;
&lt;p&gt;Of course, all of these folks are mathematicians, and many mathematicians famously look down their noses at applied mathematicians.&lt;/p&gt;
&lt;p&gt;Consider the famous claim by G. H. Hardy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have never done anything 'useful'. No discovery of mine has made, or is likely to make, directly or indirectly, for good or ill, the least difference to the amenity of the world.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mind you that didn't stop folks from later putting his ideas to work in thermodynamics and quantum physics, and the gap between pure mathematics and theoretical physics seems to be narrowing every year.&lt;/p&gt;
&lt;p&gt;To me the difference between a mathematician and an applied mathematician is one of focus.&lt;/p&gt;
&lt;p&gt;Often a mathematician will start with an abstraction and try to find things that fit, to help give intuition for folks for the more general concept.&lt;/p&gt;
&lt;p&gt;Conversely, an applied mathematician will typically start with a thing, and try to find abstractions that capture its essence, giving rise to insight into its behavior. Mathematics is used to provide a bit of &lt;a href=&quot;http://en.wikipedia.org/wiki/Go_motion#Petroleum_jelly&quot;&gt;vaseline for the lens&lt;/a&gt;, blurring away the parts you don't want to focus on.&lt;/p&gt;
&lt;p&gt;We aren't pulling legs off a centipede and seeing if it can go. We're trying to understand the behavior of a spider without gluing an extra 92 legs onto its thorax and then wondering why it lacks the strength to climb back into its web.&lt;/p&gt;
&lt;p&gt;While not all centipede mathematicians are applied mathematicians, some really do just want to pull apart their abstractions in a Mengelean fashion and understand why they tick, but the art of applying mathematics is largely an exercise in centipede mathematics. At one extreme, roboticists often pull or &lt;a href=&quot;http://www.washingtonpost.com/wp-dyn/content/article/2007/05/05/AR2007050501009.html&quot;&gt;blow the legs off&lt;/a&gt; their centipedes literally to see how they'll adjust their gait.&lt;/p&gt;
&lt;h2 id=&quot;the-view-from-the-bottom&quot;&gt;The View from the Bottom&lt;/h2&gt;
&lt;p&gt;Of course, all of these folks are mathematicians, so they can look down on the lowly computer scientist, the practitioner of an artform that is delightfully neither truly about computers nor, properly, a science.&lt;/p&gt;
&lt;p&gt;Virtually everything we touch in computer science arose from a form of centipede mathematics.&lt;/p&gt;
&lt;p&gt;Constructive logic is the natural vocabulary of computer science. You obtain it by ripping double-negation out of classical logic and watching the system hobble along. The idealized category of Haskell types &lt;code&gt;Hask&lt;/code&gt; is effectively used as a constructive analogue to &lt;code&gt;Set&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;theseus-and-procrustes&quot;&gt;Theseus and Procrustes&lt;/h2&gt;
&lt;p&gt;We can, however, turn this perspective around.&lt;/p&gt;
&lt;p&gt;In Greek mythology, Procrustes served as the final trial of Theseus during his travels to Athens. He would offer travelers along the road food and a night's lodging in a bed he promised would be a perfect fit.&lt;/p&gt;
&lt;p&gt;Upon their repose, he would proceed to set to work on them with a hammer to stretch them to fit, or an axe to cut off any excess length, forcing them to fit the bed.&lt;/p&gt;
&lt;p&gt;Worse, Procrustes kept two beds, so no traveler could ever measure up. While Theseus ultimately triumphed over the giant Procrustes, forcing him to fit his own bed by cutting off his head and feet, the concept lives on. In literary analysis, a &lt;a href=&quot;http://en.wikipedia.org/wiki/Procrustes#Contemporary_usage&quot;&gt;Procrustean bed&lt;/a&gt; is an arbitrary standard to which exact conformity is enforced.&lt;/p&gt;
&lt;h2 id=&quot;procrustean-mathematics&quot;&gt;Procrustean Mathematics&lt;/h2&gt;
&lt;p&gt;Traditional mathematicians finds themselves often forced into the role of Procrustes with many such theoretical beds at their disposal, they can proceed by cutting off bits or adjoining pieces to satisfy the requirements of whatever mathematical construct in which they want to work.&lt;/p&gt;
&lt;p&gt;Conversely, the applied mathematician or computer scientist often finds themself in a situation where they care more about their problem patient, but can't find a bed to fit. Being a bit less psychopathic, they must set aside mathematical taste and adjust the &lt;a href=&quot;http://www.youtube.com/watch?v=2q4JDpDSXMw&quot;&gt;bed&lt;/a&gt;. This is an exercise in centipede mathematics, the bed itself doesn't fit, so they rip parts off of it until it does.&lt;/p&gt;
&lt;p&gt;We don't do this because we hate the bed, but because we are concerned for the patient.&lt;/p&gt;
&lt;p&gt;The mathematician is looking out for the needs of the abstraction. The applied mathematician or computer scientist is looking out to maximize the fit for a given domain.&lt;/p&gt;
&lt;h2 id=&quot;the-operation-was-a-success&quot;&gt;The Operation Was a Success&lt;/h2&gt;
&lt;p&gt;In a &lt;a href=&quot;http://www.reddit.com/r/haskell/comments/1ou06l/improving_applicative_donotation/&quot;&gt;recent thread&lt;/a&gt; on Reddit it was suggested that every &lt;code&gt;Semigroup&lt;/code&gt; should be extended to a &lt;code&gt;Monoid&lt;/code&gt; and then we could be done with the need for the more refined concept.&lt;/p&gt;
&lt;p&gt;We can actually often accomplish this. Consider this &lt;code&gt;Semigroup&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getFirst&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  m &amp;lt;&amp;gt; _ = m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you really want a &lt;code&gt;Monoid&lt;/code&gt; you can lay about with Procrustes' hammer and adjoin a unit.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getFirst&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Semigroup&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; &amp;lt;&amp;gt; m = m
  m             &amp;lt;&amp;gt; _ = m
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

  &lt;span class=&quot;hljs-type&quot;&gt;First&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; `mappend` m = m
  m             `mappend` _ = m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now our object has grown a bit more complicated, but we can use it with all the usual &lt;code&gt;Foldable&lt;/code&gt; machinery.&lt;/p&gt;
&lt;p&gt;Sometimes the patient may be better off for his extra parts, but you may kill other properties you want along the way, or have to consider impossible cases.&lt;/p&gt;
&lt;p&gt;Having &lt;code&gt;Semigroup&lt;/code&gt; as a more fine-grained constraint does enable us to handle the empty case once and for all, and lets us fold over a &lt;code&gt;NonEmpty&lt;/code&gt; container with more things and capture the non-empty nature of something via &lt;code&gt;Foldable1&lt;/code&gt; and it simplifies &lt;code&gt;First&lt;/code&gt;'s implementation considerably, but requires you to use something like &lt;code&gt;Option&lt;/code&gt; to lift it into a &lt;code&gt;Monoid&lt;/code&gt; you can use for a general purpose list.&lt;/p&gt;
&lt;p&gt;Here this is simply a matter of taste, but that isn't always the case.&lt;/p&gt;
&lt;h2 id=&quot;but-the-patient-died&quot;&gt;... But the Patient Died&lt;/h2&gt;
&lt;p&gt;If you try to stretch any particular &lt;code&gt;Comonad&lt;/code&gt; to fit &lt;code&gt;Alternative&lt;/code&gt;, you have to deal with the fact that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; empty :: a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This strongly implies no such beast can exist, and so the &lt;code&gt;Comonad&lt;/code&gt; must die to make room for the &lt;code&gt;Alternative&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;We have to give up either &lt;code&gt;empty&lt;/code&gt; or &lt;code&gt;extract&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The type system has taken on the role of the serial killer &lt;a href=&quot;http://en.wikipedia.org/wiki/Saw_%28film%29&quot;&gt;Saw&lt;/a&gt;, sadistically forcing us to choose which of our friends will lose a limb.&lt;/p&gt;
&lt;p&gt;Even if you want to disavow centipede mathematics, you're going to be forced to occasionally put your abstractions on the chopping block, or abandon rigor.&lt;/p&gt;
&lt;h2 id=&quot;haskell&quot;&gt;Haskell&lt;/h2&gt;
&lt;p&gt;You may be able to upgrade an &lt;code&gt;Applicative&lt;/code&gt; parser to one that is a &lt;code&gt;Monad&lt;/code&gt;, perhaps at the cost of parallelism.&lt;/p&gt;
&lt;p&gt;Haskell's type system is very good at expressing a few well chosen abstractions. &lt;code&gt;Monad&lt;/code&gt; used to be the golden hammer of the Haskell community, until we found out that &lt;code&gt;Applicative&lt;/code&gt; functors exist and are useful for capturing context-free code, where the control flow doesn't vary based on previous results.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Arrow&lt;/code&gt; was introduced along the way, but later had a smaller &lt;code&gt;Category&lt;/code&gt; class carved out of it.&lt;/p&gt;
&lt;p&gt;Typeclasses in Haskell tend to force us into a small set of bed sizes, because it is relatively bad at code reuse across fine-grained class hierarchies.&lt;/p&gt;
&lt;p&gt;Each attempt at refining the class hierarchy carries with it a price that library implementors and users who instantiate the classes must now write more methods. Worse, they must often do so without access to the full gamut of extra laws obtained further down in the class hierarchy, because they don't have a tenable way of offering defaults for superclass methods when they write a subclass.&lt;/p&gt;
&lt;p&gt;Even with one of the superclass default proposals, you get no real code reuse for any form of transformer, and the existing default signature mechanism runs &quot;the wrong way&quot; in such a way that it even forces you to put everything in the same module.&lt;/p&gt;
&lt;p&gt;The initial arguments against a fine-grained class hierarchy in Haskell arose from the same place as the denigration of centipede mathematics, but they are butressed by the pragmatic concern that there is real pain in an accurate class hierarchy caused by the design of the language.&lt;/p&gt;
&lt;p&gt;These are valid concerns!&lt;/p&gt;
&lt;p&gt;Arguments in favor of a finer-grained hierarchy arise from a desire to avoid flooding the namespace with redundant operations, and to capture the relationship between things. It arises from caring about the needs of the things you want to be able to reason about, rather than capturing just the examples that happen to measure up to an arbitrary standard.&lt;/p&gt;
&lt;p&gt;These are also valid concerns!&lt;/p&gt;
&lt;h2 id=&quot;semigroupoids&quot;&gt;Semigroupoids&lt;/h2&gt;
&lt;p&gt;My &lt;code&gt;semigroupoids&lt;/code&gt; package was originally written because I couldn't work with product categories in Haskell, but needed them in code.&lt;/p&gt;
&lt;p&gt;I still can't, due to the presence of &lt;code&gt;Any&lt;/code&gt; as a distinguished member of every kind in Haskell.&lt;/p&gt;
&lt;p&gt;Along the way, I dug up the &lt;a href=&quot;http://ncatlab.org/nlab/show/horizontal+categorification&quot;&gt;&lt;em&gt;-oid&lt;/em&gt;-ification&lt;/a&gt; of a &lt;code&gt;Semigroup&lt;/code&gt;, also known as a &lt;a href=&quot;http://ncatlab.org/nlab/show/semicategory&quot;&gt;semicategory&lt;/a&gt; to capture the portions of the product category that we &lt;em&gt;can&lt;/em&gt; write nicely in Haskell today.&lt;/p&gt;
&lt;p&gt;When we look at the Kleisli category of things that are not quite a &lt;code&gt;Monad&lt;/code&gt;, or the static arrow category of things that are not quite &lt;code&gt;Applicative&lt;/code&gt;, we wind up with mere a &lt;code&gt;Semigroupoid&lt;/code&gt; rather than a &lt;code&gt;Category&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But where do we find such examples?&lt;/p&gt;
&lt;p&gt;Consider the lowly &lt;code&gt;IntMap&lt;/code&gt;. It cannot be made an instance of &lt;code&gt;Applicative&lt;/code&gt; or &lt;code&gt;Monad&lt;/code&gt; directly.&lt;/p&gt;
&lt;p&gt;We have three options to proceed if we want to work with something like &lt;code&gt;(&amp;lt;*&amp;gt;)&lt;/code&gt; or &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; on it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We can clutter the namespace with a completely ad hoc combinator that we can't abstract over.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can try to adjoin a universal default. This means that you have to kill the &lt;code&gt;Foldable&lt;/code&gt; and &lt;code&gt;Traversable&lt;/code&gt; instances for it, or deal with the fact that they basically return nonsense. It also means that you either have to give up the ability to delete from the map, or accept the fact that you aren't really modeling &lt;code&gt;(Int -&amp;gt; Maybe b)&lt;/code&gt; any more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can engage in a bit of centipede mathematics, ripping off the &lt;code&gt;pure&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; from &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;Monad&lt;/code&gt; respectively to get a semi-&lt;code&gt;Applicative&lt;/code&gt; and a semi-&lt;code&gt;Monad&lt;/code&gt;, which I unartfully called &lt;code&gt;Apply&lt;/code&gt; and &lt;code&gt;Bind&lt;/code&gt;, in &lt;code&gt;semigroupoids&lt;/code&gt;. Now we've respected the needs of the domain object, at the expense of a finer grained class hierarchy.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In a perfect world, from the perspective of the centipede mathematician, &lt;code&gt;Apply&lt;/code&gt; and &lt;code&gt;Bind&lt;/code&gt; would occupy a place of privilege in the class hierarchy.&lt;/p&gt;
&lt;p&gt;However, to the Procrustean mathematicians who are only really concerned with &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;Monad&lt;/code&gt;, and who can't be bothered to deal with the finer grained hierarchy, such a refinement of the hierarchy merely adds cognitive overhead. They are happy to discard these examples in favor of a simpler, more teachable, meta-theory.&lt;/p&gt;
&lt;p&gt;Both of these perspectives are valid.&lt;/p&gt;
&lt;h2 id=&quot;extensible-effects&quot;&gt;Extensible Effects&lt;/h2&gt;
&lt;p&gt;To unfairly cast Oleg Kiselyov in the role of Procrustes with Edwin Brady as his understudy, we can look at the modeling of &lt;a href=&quot;http://lambda-the-ultimate.org/node/4786&quot;&gt;extensible effects&lt;/a&gt; in this same light.&lt;/p&gt;
&lt;p&gt;Lawvere theories offer us too small a bed to fit many of the effects we care to model, such as continuation passing. This is why that effect is ignored by Edwin Brady's handling of effects for Idris. They just don't fit.&lt;/p&gt;
&lt;p&gt;On the other hand, Oleg offers us a second bed that is much bigger, his &lt;code&gt;Eff&lt;/code&gt; monad is the result of applying &lt;code&gt;Codensity&lt;/code&gt; to a Lawvere Theory. Now it's the job of the handler to deal with the impossible cases.&lt;/p&gt;
&lt;p&gt;We're forced to set about with Procrustes' hammer to embed many monads, like &lt;code&gt;Reader&lt;/code&gt; into a domain that is too large.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; ((-&amp;gt;) s) a ~
&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; s -&amp;gt; r) -&amp;gt; s -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is strong enough to implement all of CPS'd &lt;code&gt;State&lt;/code&gt;. If you pass it &lt;code&gt;(,)&lt;/code&gt; for its first argument you get &lt;code&gt;s -&amp;gt; (a, s)&lt;/code&gt;! It is only by convention and hiding that we can restrict such a reader down to size.&lt;/p&gt;
&lt;div align=&quot;center&quot; style=&quot;padding-bottom: 10px&quot;&gt;&lt;img alt=&quot;Illustration from Procrustean Mathematics&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/cd8b8abf9816-suit.jpg&quot;&gt;&lt;/div&gt;
&lt;p&gt;This means that the compiler has really no chance of ever optimizing the code properly as it must always live in fear that you could change the environment, even though the handler never will. This forces a single thread of execution through otherwise parallelizable code.&lt;/p&gt;
&lt;p&gt;We improve the adjustability of this bed by switching from the &lt;code&gt;Codensity&lt;/code&gt; construction to an arbitrary right Kan extension, like my old &lt;code&gt;monad-ran&lt;/code&gt; package did. This lets the bed conform to the shape of &lt;code&gt;Reader&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; ((-&amp;gt;) s) a ~
&lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; ((-&amp;gt;) s) a ~
&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; r) -&amp;gt; s -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is just a CPS'd function, when passed &lt;code&gt;id&lt;/code&gt; we recover &lt;code&gt;(s -&amp;gt; a)&lt;/code&gt;. It is no longer large enough to model all of &lt;code&gt;State&lt;/code&gt; and properly captures the features we want.&lt;/p&gt;
&lt;p&gt;Yet even this bed is still too small for some patients. The infinite usecases of lazy writer and lazy state monads still cannot be made to fit at all. This destroys many interesting use cases of the &lt;a href=&quot;https://hackage.haskell.org/package/tardis-0.3.0.0/docs/Control-Monad-Tardis.html&quot;&gt;Tardis&lt;/a&gt;. Admittedly they are the kinds of things that tie users in knots. Perhaps like an appendix removal, your patients will not miss those parts.&lt;/p&gt;
&lt;p&gt;However, many monads for syntax trees like the transformer used by &lt;code&gt;bound&lt;/code&gt; cannot be adapted without an &lt;em&gt;asymptotic&lt;/em&gt; performance hit, causing you to redo whole calculations every time you want to pattern match on the result.&lt;/p&gt;
&lt;p&gt;From the standpoint of the Procrustean mathematician, the extensible effects approach is fairly elegant, it provides a single bed into which many common effects can fit.&lt;/p&gt;
&lt;p&gt;The elegance of this approach makes it very appealing!&lt;/p&gt;
&lt;p&gt;However, it isn't roomy enough to hold all of the current effects we can capture with monad transformers. Without upgrading to &lt;code&gt;Ran&lt;/code&gt;, many effects are forced into a model that is too big, where you have to handle many impossible conditions that are merely ruled out by convention. On the other side, the inability to handle a number of cases that we do use in practice is also somewhat of a bad sign.&lt;/p&gt;
&lt;p&gt;This is why I can bring myself to view extensible effects as a usful way to think about effects, but I can't view it as a full replacement for the monad transformer approach.&lt;/p&gt;
&lt;p&gt;Monad transformers do pay an &lt;code&gt;O(n^2)&lt;/code&gt; complexity tax, describing how everything commutes over everything else, but &lt;code&gt;n&lt;/code&gt; is typically not that big of a number.&lt;/p&gt;
&lt;p&gt;The abilty to handle the extra cases that don't fit the extensible effects approach means I can't bring myself to just relegate them to the waste bin of history. As an applied mathematician / computer scientist, I still need to handle those effects!&lt;/p&gt;
&lt;p&gt;Concerns about the need to write &lt;code&gt;lift . lift . lift&lt;/code&gt;, seem to arise from a particularly awkward style of use that I frankly never see in real code. There are ways to handle this and the multiple-state issues using tools we have, such as lenses. I'll relegate both of these concerns to another post.&lt;/p&gt;
&lt;h2 id=&quot;lenses&quot;&gt;Lenses&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;lens&lt;/code&gt; package is very much an exercise in building a very fine grained set of distinctions and trying to make it so you can say very precisely what constraints you want to impose on each operator.&lt;/p&gt;
&lt;p&gt;Alternative designs like &lt;code&gt;fclabels&lt;/code&gt; capture a different trade-off between factors.&lt;/p&gt;
&lt;p&gt;I, personally, find that the ability to express a &lt;code&gt;Fold&lt;/code&gt; or &lt;code&gt;Getter&lt;/code&gt; is worth the added complexity of the representation. Your mileage may vary.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fclabels&lt;/code&gt; forces you to stretch each such thing into a form where you cannot express any laws, and then lays about with Procrustes' axe cutting of a number of abstractions we've found useful at the top end of the lens ecosystem, for Indexed traversals and the like.&lt;/p&gt;
&lt;p&gt;It is a pretty clean exercise in Procrustean mathematics, though. If you fit into the abstraction it models comfortably, you'll never feel the bite of the axe.&lt;/p&gt;
&lt;p&gt;Even &lt;code&gt;lens&lt;/code&gt;, with its deep hierarchy, occasionally cuts you with Procrustes' axe. There are some constructions that just don't fit the domain. For instance &lt;code&gt;lens&lt;/code&gt; offers no tool for validating input -- a &lt;code&gt;Lens' s a&lt;/code&gt; must accept any such &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is a tension between these design criteria as with &lt;code&gt;Comonad&lt;/code&gt; and &lt;code&gt;Alternative&lt;/code&gt;. Something had to give.&lt;/p&gt;
&lt;p&gt;Lens chooses a different point on the design curve than &lt;code&gt;fclabels&lt;/code&gt;. The choice we made was to gain a great deal of expressive power and ability to reason about the code with laws in exchange for validation.&lt;/p&gt;
&lt;h2 id=&quot;the-view-from-the-middle&quot;&gt;The View from the Middle&lt;/h2&gt;
&lt;p&gt;It is important to realize that modifying the abstraction/bed or modifying the problem/patient are both options.&lt;/p&gt;
&lt;p&gt;Sometimes you can easily adapt the problem to the mathematical construct, and sometimes the mathematical construct can be easily adapted to the problem.&lt;/p&gt;
&lt;p&gt;When we add laws and operatons to an abstraction, we wind up with fewer examples.&lt;/p&gt;
&lt;p&gt;If we work parametrically over an abstraction, the weaker the requirements we put on our inputs, the more scenarios we can cover.&lt;/p&gt;
&lt;p&gt;Other times one or the other is up against a hard constraint. It is very important to distinguish between the normative concerns of taste and the very real concerns that some times one or the other of these things cannot give, as in the &lt;code&gt;Comonad/Alternative&lt;/code&gt; case above.&lt;/p&gt;
&lt;p&gt;To argue against a straw man, giving up either one of these degrees of freedom unilaterally strikes me as absurd.&lt;/p&gt;
&lt;p&gt;A hundred years ago, nobody cared about the foundations of mathematics, then came Russell and Whitehead, but their encoding was in many ways too dense and full of incredibly fine-grained distinctions.&lt;/p&gt;
&lt;p&gt;Competing tensions like this gave us the mathematical world we inhabit today.&lt;/p&gt;
&lt;p&gt;The choice of how to balance these factors, to abstract over enough problem domans to be useful without needlessly quibbling over impossibly fine-grained distinctions is really the true role of taste in library design and in mathematics, and tastes vary over time.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;October 25th, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/editorial-procrustean-mathematics/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cache-Oblivious Maps</title><link>https://comonad.com/reader/talks/kmett-2013-cache-oblivious-maps/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2013-cache-oblivious-maps/</guid><pubDate>Fri, 18 Oct 2013 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 18 October 2013&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;P3pLDpbzqCw&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=P3pLDpbzqCw&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Cache-Oblivious Maps — Bay Area Haskell User Group at Mozilla San Francisco.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=P3pLDpbzqCw&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://ekmett.github.io/presentations/Cache-Oblivious%20Data%20Structures.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://raw.githubusercontent.com/ekmett/ekmett.github.com/master/presentations/Cache-Oblivious%20Data%20Structures.key&quot;&gt;slides source&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2013-cache-oblivious-maps/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Functional Reporting</title><link>https://comonad.com/reader/talks/kmett-2013-functional-reporting/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2013-functional-reporting/</guid><pubDate>Sun, 22 Sep 2013 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 22 September 2013&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;o3m2NkusI9k&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=o3m2NkusI9k&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Functional Reporting — CUFP2013.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=o3m2NkusI9k&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://ekmett.github.io/presentations/Functional%20Reporting.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2013-functional-reporting/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cellular Automata — Part III: A World in a Bottle</title><link>https://comonad.com/reader/2013/cellular-automata-part-3/</link><guid isPermaLink="false">https://comonad.com/reader/2013/cellular-automata-part-3/</guid><pubDate>Sun, 15 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 September 2013&lt;/p&gt;&lt;p&gt;In &lt;a href=&quot;https://comonad.com/reader/2014/cellular-automata-part-1/&quot;&gt;Part I&lt;/a&gt;, I showed how we can build up cellular automata in Haskell and render them to the web as custom SVGs. In &lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/&quot;&gt;Part II&lt;/a&gt;, I replaced the SVG writer with a hand-rolled PNG writer.&lt;/p&gt;
&lt;p&gt;The last article got lost in the weeds playing with PNG writing and the comonadic structure of folds. This time around I want to go back to focusing on the automata themselves. If you haven't read those yet, I'd highly recommend at least skimming at least the first one to familiarize yourself with its contents before proceeding.&lt;/p&gt;
&lt;p&gt;One of the issues I raised back in part I was that &lt;code&gt;Store&lt;/code&gt; was in some sense too big to describe automata because the automata could know and use their absolute position information when computing their answers. I'd like to fix that.&lt;/p&gt;
&lt;p&gt;Another thing I hinted at was that it was possible to build automata on strange topologies. I'd like to show how we can enable interesting topologies through the very act of fixing the previous problem.&lt;/p&gt;
&lt;h2 id=&quot;moves-like-jagger&quot;&gt;Moves like Jagger&lt;/h2&gt;
&lt;p&gt;The problem that we had was that the &lt;code&gt;Store&lt;/code&gt;/&lt;code&gt;Context&lt;/code&gt; comonad gave you direct access to the current location. So nothing prevents a rule from acting very differently in position 34 than it does anywhere else in the space.&lt;/p&gt;
&lt;p&gt;We can fix that by introducing a notion of a relative movement rather than just having absolute positioning.&lt;/p&gt;
&lt;p&gt;Now, we an define our notion of a rule as something that can use relative position information alone, and can combine answers to questions about nearby locations to generate a local answer.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a = (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Under this scheme, our old 2-color Wolfram-style &lt;a href=&quot;http://mathworld.wolfram.com/ElementaryCellularAutomaton.html&quot;&gt;elementary cellular automata&lt;/a&gt; rules look like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w f = testBit w $ &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits .~ (f &amp;lt;$&amp;gt; [minBound .. maxBound])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we want to increase the &quot;speed of light&quot; we can make a new &lt;code&gt;Move&lt;/code&gt; type, and generalize &lt;code&gt;rule&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move2&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;RR&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;LL&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; n, &lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt; n) =&amp;gt; n -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w f = testBit w $ &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits .~ (f &amp;lt;$&amp;gt; [minBound .. maxBound])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now &lt;code&gt;rule&lt;/code&gt; can work for pretty much any enumerable, bounded move type and provide you with Wolfram-like rules.&lt;/p&gt;
&lt;p&gt;Now we just need some way to act on a &lt;code&gt;Rule&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&quot;act-upon-the-world&quot;&gt;Act Upon The World&lt;/h2&gt;
&lt;p&gt;It turns out it is better to think of our rules as acting upon our automaton's topology rather than vice versa.&lt;/p&gt;
&lt;p&gt;We can do that by describing the &lt;a href=&quot;http://en.wikipedia.org/wiki/Semigroup_action&quot;&gt;&quot;action&quot;&lt;/a&gt; of our movements on our position. If our movements were always composable, then we would want this to be a &quot;semigroup action&quot;, or even a &quot;monoid action&quot; if we had a unit. If you are curious to know more about monoid actions, I'd encourage you to read &lt;a href=&quot;http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf&quot;&gt;Brent's Pearl&lt;/a&gt;, but then if you've been following all of the myriad links I've been throwing out from the beginning, then you may already have done so. I cited it for other reasons back in Part I.&lt;/p&gt;
&lt;p&gt;However, since we want to ensure we have a discrete &quot;speed of light&quot; governing information travel in our automaton and we don't want to deal with relativistic effects, for now, let's just not let them compose for now.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s = m -&amp;gt; s -&amp;gt; s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we wanted to be more correct, we should likely have different universe types for each action, but it'll suffice to let the action define our topology instead.&lt;/p&gt;
&lt;p&gt;An action transforms a move into a function that transforms the current location.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;flat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;flat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; i = i-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;flat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; i = i
&lt;span class=&quot;hljs-title&quot;&gt;flat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; i = i+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another example topology for the first &lt;code&gt;Move&lt;/code&gt; type we started with would be to just treat the movement as relative in a world.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; n m i = flat m i `mod` n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we just need to define the step function:&lt;/p&gt;
&lt;h2 id=&quot;i-dream-of-genie&quot;&gt;I Dream of Genie&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's say for a minute that we didn't know how to write this! What could we do?&lt;/p&gt;
&lt;p&gt;Back in 2005, Lennart Augustsson &lt;a href=&quot;http://permalink.gmane.org/gmane.comp.lang.haskell.general/12747&quot;&gt;wrote&lt;/a&gt; a wonderful tool named &lt;code&gt;djinn&lt;/code&gt; for doing just this sort of thing.&lt;/p&gt;
&lt;p&gt;From the release announcement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For the curious, Djinn uses a decision procedure for intuitionistic
propositional calculus due to Roy Dyckhoff.  It's a variation of
Gentzen's LJ system.  This means that (in theory) Djinn will always
find a function if one exists, and if one doesn't exist Djinn will
terminate telling you so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So let's use it!&lt;/p&gt;
&lt;p&gt;On &lt;a href=&quot;https://webchat.freenode.net/?channels=haskell&amp;uio=d4&quot;&gt;irc.freenode.net&lt;/a&gt;, our well-loved mechanical assistant &lt;code&gt;lambdabot&lt;/code&gt; has a version of &lt;code&gt;djinn&lt;/code&gt; installed, which is available via the &lt;code&gt;@djinn&lt;/code&gt; command.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] edwardk:   @djinn a -&amp;gt; a
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] lambdabot: f a = a
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] edwardk:   @djinn a -&amp;gt; b -&amp;gt; c
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] lambdabot: &lt;span class=&quot;hljs-comment&quot;&gt;-- f cannot be realized.&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] edwardk:   @djinn a -&amp;gt; b -&amp;gt; a
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] lambdabot: f a _ = a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;She doesn't know anything about our &lt;code&gt;Context&lt;/code&gt;, though, so let's help her out.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;35&lt;/span&gt;] edwardk: @djinn-add &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a b t = &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now she's fully capable of deriving for us the definitions for extract:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;37&lt;/span&gt;] edwardk:   @djinn &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a a t -&amp;gt; t
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;37&lt;/span&gt;] lambdabot: f a =
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;37&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;37&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; b c -&amp;gt; b c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and even how to &lt;code&gt;extend&lt;/code&gt; &lt;code&gt;Context&lt;/code&gt; as an indexed comonad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;39&lt;/span&gt;] edwardk:   @djinn (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; b c t -&amp;gt; r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a c t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a b r
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;39&lt;/span&gt;] lambdabot: f a b =
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;39&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;39&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; c d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (\ e -&amp;gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; c e)) d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, let's teach her about rules and actions.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;42&lt;/span&gt;] edwardk: @djinn-add &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a = (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;42&lt;/span&gt;] edwardk: @djinn-add &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s = m -&amp;gt; s -&amp;gt; s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and ask her for a definition for &lt;code&gt;step&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;43&lt;/span&gt;] edwardk:   @djinn &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;43&lt;/span&gt;] lambdabot: f _ a b =
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;43&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;43&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; c d -&amp;gt; a (\ _ -&amp;gt; c d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ack! Something went wrong.&lt;/p&gt;
&lt;p&gt;What happened was that the problem was under-constrained.&lt;/p&gt;
&lt;p&gt;She didn't have to apply the action, so she didn't.&lt;/p&gt;
&lt;p&gt;Similarly, if we try for the unindexed version of &lt;code&gt;extend&lt;/code&gt;, we run into the same problem!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;45&lt;/span&gt;] edwardk:   @djinn (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a a t -&amp;gt; r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a a t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; a a r
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;45&lt;/span&gt;] lambdabot: f a b =
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;45&lt;/span&gt;] lambdabot:      &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;45&lt;/span&gt;] lambdabot:      &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; c d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (\ e -&amp;gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (\ _ -&amp;gt; c d) e)) d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, let's split apart the positive and negative uses of 's' in our original problem.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;46&lt;/span&gt;] edwardk:   @djinn-add &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Acts&lt;/span&gt; m s t = m -&amp;gt; s -&amp;gt; t&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;46&lt;/span&gt;] edwardk:   @djinn &lt;span class=&quot;hljs-type&quot;&gt;Acts&lt;/span&gt; m s t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s t a -&amp;gt; a
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;46&lt;/span&gt;] lambdabot: f a b c =
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;46&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; c &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
[&lt;span class=&quot;hljs-number&quot;&gt;03&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;46&lt;/span&gt;] lambdabot:  &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; d e -&amp;gt; b (\ f -&amp;gt; d (a f e))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There we have it!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; a b (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; d e) = b (\f -&amp;gt; d (a f e))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we want to clean that up a bit:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; top r (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; f s) = r (f . flip top s)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;thats-all-for-now&quot;&gt;Thats All For Now&lt;/h2&gt;
&lt;p&gt;Putting all of that together a greyscale version of the PNG writer from my Mandelbrot snippet yields the following code.&lt;/p&gt;
&lt;p&gt;Click Run!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/cellular-automata-part-3/#topology-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Codec.Compression.Zlib
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens.Internal.Context
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary.Put
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; F
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; List
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.MemoCombinators
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a = (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w f = testBit w $ &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits .~ (f &amp;lt;$&amp;gt; [minBound .. maxBound])

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s = m -&amp;gt; s -&amp;gt; s&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; m &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; i = (i-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) `mod` m
&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; i = i
&lt;span class=&quot;hljs-title&quot;&gt;modulo&lt;/span&gt; m &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; i = (i+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) `mod` m

&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Act&lt;/span&gt; m s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rule&lt;/span&gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;step&lt;/span&gt; top r (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; f s) = r (f . flip top s)

&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; s =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a]
&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt;.iterate (tab . extend f) . tab &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  tab (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; g s) = &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (integral g) s

&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; [[&lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;]]
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; r x m0 = fmap line $ loop (step (modulo m0) (rule r)) $ &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (==&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  line = fmap bw . window (x `div` &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)
  bw &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;  = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  bw &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;
  window w = iexperiment $ \ s -&amp;gt; [s-w..s+w]

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = complement . &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.foldl' f &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  f r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; `xor` crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;)
  crcs = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral)
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; h b = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b)
  putLazyByteString h
  putLazyByteString b
  putWord32be $ crc32 (h &amp;lt;&amp;gt; b)

&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; [[&lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;]] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; w h fs = runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putLazyByteString &lt;span class=&quot;hljs-string&quot;&gt;&quot;\x89PNG\r\n\x1a\n&quot;&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IHDR&quot;&lt;/span&gt; $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    putWord32be (fromIntegral w)
    putWord32be (fromIntegral h)
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 8 bit&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- greyscale&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $
    compressWith defaultCompressParams { compressLevel = bestSpeed } $
    runPut $ &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.forM_ (&lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.take h fs) $ \xs -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.forM_ (&lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.take w xs) put
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IEND&quot;&lt;/span&gt; mempty

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yesod&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;
mkYesod &quot;&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&quot; [parseRoutes| / &lt;span class=&quot;hljs-type&quot;&gt;ImageR&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GET&lt;/span&gt; |]

main :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
main = warpEnv &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;


getImageR :: &lt;span class=&quot;hljs-type&quot;&gt;MonadHandler&lt;/span&gt; m =&amp;gt; m &lt;span class=&quot;hljs-type&quot;&gt;TypedContent&lt;/span&gt;
getImageR = sendResponse $ toTypedContent (&lt;span class=&quot;hljs-title&quot;&gt;typePng&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;toContent&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;img&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  img = png &lt;span class=&quot;hljs-number&quot;&gt;280&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;280&lt;/span&gt; $ run &lt;span class=&quot;hljs-number&quot;&gt;110&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;280&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all of that we're still well under a hundred lines.&lt;/p&gt;
&lt;p&gt;We're not limited to simple small world topologies, but if you want to connect random points in space, you're probably better off doing so in a 2d automaton, simply because there are more interesting combinations.&lt;/p&gt;
&lt;p&gt;In the interest of full disclosure, Djinn isn't perfect. It can't deal with rank-n types. It also doesn't really understand typeclasses as they behind the scenes &lt;em&gt;also&lt;/em&gt; involve rank-n types. It is however, an incredibly useful tool that helps showcase the power of &lt;a href=&quot;http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf&quot;&gt;free theorems&lt;/a&gt; to constrain down the space of possible implementations to the point where only reasonable programs can type check at all.&lt;/p&gt;
&lt;p&gt;By making our programs &lt;em&gt;more&lt;/em&gt; generic we are able to restrict them to fewer possible implementations, leaving us with only one reasonable thing that typechecks.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 15th, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/cellular-automata-part-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Conquering Folds</title><link>https://comonad.com/reader/2013/conquering-folds/</link><guid isPermaLink="false">https://comonad.com/reader/2013/conquering-folds/</guid><pubDate>Fri, 13 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 13 September 2013&lt;/p&gt;&lt;p&gt;I've been posting a lot about comonads lately, mostly for working with folds of various flavors over lists.&lt;/p&gt;
&lt;p&gt;This time I want to take a different tack and use the tools we've been building to perform certain computations over arbitrary polynomial data types in parallel with arbitrary cuts of the data potentially distributed on different hosts.&lt;/p&gt;
&lt;h2 id=&quot;close-encounters-of-the-third-kind&quot;&gt;Close Encounters of the Third Kind&lt;/h2&gt;
&lt;p&gt;The techniques I want to use here derive from an old &quot;folklore&quot; tool in the constructive algorithmics community known as the &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.45.2247&amp;rep=rep1&amp;type=pdf&quot;&gt;&quot;Third Homomorphism Theorem&quot;&lt;/a&gt;, which was written up back in 1995 by &lt;a href=&quot;http://www.cs.ox.ac.uk/people/jeremy.gibbons/&quot;&gt;Jeremy Gibbons&lt;/a&gt;, but which dates back further to a conjecture by &lt;a href=&quot;http://web.comlab.ox.ac.uk/oucl/people/richard.bird.html&quot;&gt;Richard Bird&lt;/a&gt; that was proven by a bored &lt;a href=&quot;http://www.kestrel.edu/home/people/meertens/&quot;&gt;Lambert Meertens&lt;/a&gt; on a train ride through the Netherlands in 1989.&lt;/p&gt;
&lt;img alt=&quot;Illustration from Conquering Folds&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/c64dfacc49d3-closeencounters1.jpg&quot;&gt;
&lt;p&gt;The Third Homomorphism Theorem basically states that if you can compute something as both a left fold and a right fold then you can compute it monoidally.&lt;/p&gt;
&lt;p&gt;It is wrapped up in slightly different vocabulary, and various treatments often forget the unit for the monoid or work with what would be non-empty lists. The terminology in the papers that talk about it focus on list homomorphisms, which are just monoid homomorphisms from the list monoid.&lt;/p&gt;
&lt;p&gt;The Third Homomorphism Theorem also provides a not-so-efficient way to derive such a &lt;code&gt;Monoid&lt;/code&gt;, that you can then hopefully improve by reasoning about your special case. In Gibbons' paper on the topic, he derives &lt;em&gt;O(n log n)&lt;/em&gt; &lt;code&gt;mergesort&lt;/code&gt; from the &lt;em&gt;O(n^2)&lt;/em&gt; &lt;code&gt;insertsort&lt;/code&gt; via the sort of equational reasoning that is the hallmark of the constructive algorithmics style.&lt;/p&gt;
&lt;p&gt;Unfortunately, you &lt;em&gt;do&lt;/em&gt; have to reason about the particular list homomorphism to make it useful, as the result is generally not terribly efficient without some effort.&lt;/p&gt;
&lt;p&gt;Sadly, the Third Homomorphism Theorem itself isn't terribly useful as an automated parallelization technique. There has actually been some progress in that area in terms of parallel skeletons, but it has been a pretty slow couple of decades.&lt;/p&gt;
&lt;p&gt;If we ignore the particulars of how the theorem itself is used, and just focus on what it means, then it does help indicate that something like &lt;code&gt;foldMap&lt;/code&gt; is a potentially powerful tool, but we've pretty much accepted that by now.&lt;/p&gt;
&lt;p&gt;In addition, the original Gibbons' paper linked above also supplied most of the examples in Conal Elliott's 2011 series on &lt;a href=&quot;http://conal.net/blog/posts/deriving-list-scans&quot;&gt;&quot;Deriving List Scans&quot;&lt;/a&gt; about 16 years earlier, and is generally good reading, so it is a good way to get your head around that style of equational reasoning.&lt;/p&gt;
&lt;h2 id=&quot;beyond-lists&quot;&gt;Beyond Lists&lt;/h2&gt;
&lt;p&gt;But the Third Homomorphism Theorem is of course all &lt;em&gt;about&lt;/em&gt; lists, so how can we use it to manipulate other things?&lt;/p&gt;
&lt;p&gt;This topic was broached by Morihata et al. in  &lt;a href=&quot;http://www.prg.nii.ac.jp/publications/2009/popl09.pdf&quot;&gt;&quot;The Third Homomorphism Theorem on Trees&quot;&lt;/a&gt;, which noted that &lt;a href=&quot;http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf&quot;&gt;Gérard Huet's notion of a zipper&lt;/a&gt; is just a &lt;em&gt;list&lt;/em&gt; of steps, and so we can apply the third &lt;em&gt;list&lt;/em&gt; homomorphism theorem to it.&lt;/p&gt;
&lt;p&gt;So if you can compute something that can push information down the tree, and which can push information up the tree, then you can derive a list homomorphism that you can use on the zipper itself, and then you can subdivide your tree however you want, and compute partial answers that you can stitch together.&lt;/p&gt;
&lt;p&gt;So, let's do that!&lt;/p&gt;
&lt;h2 id=&quot;clowns-and-jokers&quot;&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=8StG4fFWHqg&quot;&gt;Clowns And Jokers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Conor McBride wrote the first section of the wonderfully-titled &lt;a href=&quot;http://strictlypositive.org/Dissect.pdf&quot;&gt;&quot;Clowns to the left of me, jokers to the right&quot;&lt;/a&gt; on how one can compute the derivatives of a polynomial functor and use it as a one hole context.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit:&lt;/em&gt; It was pointed out to me on reddit that perhaps I should have cited the more directly relevant &lt;a href=&quot;http://strictlypositive.org/diff.pdf&quot;&gt;The Derivative of a Regular Type is its Type of One-Hole Contexts&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;My first attempt at writing this up actually used GHC.Generics to derive the zippers automatically, based on Conor's formulae. Unfortunately, the automatically generated zippers aren't really fit for human consumption.&lt;/p&gt;
&lt;p&gt;Consequently, I'm going to be asking the user to describe their derivatives manually, and I'll try to keep the set of steps minimal.&lt;/p&gt;
&lt;p&gt;In particular, I'm going to be working with some kind of recursive data type &lt;code&gt;t&lt;/code&gt;, for which I'll assume it can be presented as the fixed point of some base functor &lt;code&gt;f&lt;/code&gt;. I'll never actually need to use &lt;code&gt;f&lt;/code&gt; directly, but when I talk about the &quot;derivative&quot; &lt;code&gt;D t&lt;/code&gt; of &lt;code&gt;t&lt;/code&gt;, I'll actually mean the derivative of the base functor for &lt;code&gt;t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The derivative of a polynomial functor is also polynomial, so we can expect &lt;code&gt;D t&lt;/code&gt; to be &lt;code&gt;Traversable&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t :: * -&amp;gt; *&lt;/span&gt;
  walk   :: &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t b)
  ...
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap = fmapDefault
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap = foldMapDefault
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse = walk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But before we continue too far we'll need to add a couple of additional methods to &lt;code&gt;Recursive&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we have a derivative of &lt;code&gt;t&lt;/code&gt;, then it is a 'one hole context'. It is one level of the base functor of &lt;code&gt;t&lt;/code&gt;, wrapped around &lt;code&gt;t&lt;/code&gt;s, with one of the &lt;code&gt;t&lt;/code&gt;s ripped out. We want some way to &lt;code&gt;plug&lt;/code&gt; that hole:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  ...
  plug   :: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t -&amp;gt; t -&amp;gt; t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also need some way to pick a path through our &lt;code&gt;t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For simplicity and to make the tools I want to build later easier to work with using standard Haskell classes I'm going to assume that you can either find a hole and name its contents or we've reached a trivial leaf.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  ...
  path :: t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t, t)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For now I'm just going to assume you can pick a path. Perhaps it'd be more interesting later on to try to choose a better path when we talk about parallelism. e.g. using &lt;a href=&quot;http://en.wikipedia.org/wiki/Heavy_path_decomposition&quot;&gt;heavy path decomposition&lt;/a&gt; or &lt;a href=&quot;http://courses.csail.mit.edu/6.897/spring05/lec/lec19.pdf&quot;&gt;long path decomposition&lt;/a&gt;, but I'll leave that to you to play with.&lt;/p&gt;
&lt;p&gt;Putting it all together we have:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t :: * -&amp;gt; *&lt;/span&gt;
  plug :: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t -&amp;gt; t -&amp;gt; t
  walk :: &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t b)
  path :: t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t, t)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is enough that we can peel apart our data type into a zipper. Remember we asserted that all the leaves were boring, there isn't any leaf value type to go with the zipper.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t = [&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t]&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;divide&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t
&lt;span class=&quot;hljs-title&quot;&gt;divide&lt;/span&gt; = unfoldr path
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If on the other hand we do have something interesting that we want to use to fill in a hole, we can plug it in by recursively folding our way up the tree.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;zipped&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; t -&amp;gt; t
&lt;span class=&quot;hljs-title&quot;&gt;zipped&lt;/span&gt; dt t = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr plug t dt
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;example-nats&quot;&gt;Example: Nats&lt;/h2&gt;
&lt;p&gt;If we take a look at the basic Peano-style natural number type in Haskell:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can talk about the type of one-hole contexts there are in its base functor, and it is easy to plug it back up, since there is only one case. Once we take the only hole for our one-hole context, there aren't any uses of the type parameter left.&lt;/p&gt;
&lt;p&gt;Similarly the &lt;code&gt;path&lt;/code&gt; only has one option for us at every turn.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;&lt;/span&gt;
  plug &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt;
  walk _ &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; = pure &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;
  path (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;, n)
  path &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;     = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'll throw a few more instances up later as we get to where we can use them.&lt;/p&gt;
&lt;p&gt;Needless to say I'm not going to get a lot of parallelism out of a &lt;code&gt;Nat&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conquering-reflection&quot;&gt;Conquering Reflection&lt;/h2&gt;
&lt;p&gt;So now we're ready to actually build our divide-and-conquer &lt;code&gt;Comonad&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a = forall b. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; b =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we're saying is, if you can reduce one level of the zipper's path to a monoidal result, where you've already reduced all of the other parts to the monoid, we can smash together all the answers and use the final calculation to give you an 'a' for your overall tree.&lt;/p&gt;
&lt;p&gt;If you were paying attention last time at the end of my post on parallelizing CRC calculations, this may look somewhat familiar, except for the fact that I've given in to peer pressure and decided to use an actual &lt;code&gt;Monoid&lt;/code&gt;, and the input type now references the same &lt;code&gt;Monoid&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can still use &lt;code&gt;reflection&lt;/code&gt; to manufacture the &lt;code&gt;Monoid&lt;/code&gt; if needed, without the user ever being any the wiser:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a p = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; p (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; $ snd $ reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; $ fst (reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p)) a b

&lt;span class=&quot;hljs-title&quot;&gt;conquer&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; t a b. &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt;
  (b -&amp;gt; a) -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t b -&amp;gt; b) -&amp;gt; (b -&amp;gt; b -&amp;gt; b) -&amp;gt; b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;conquer&lt;/span&gt; k h m z = reify (m,z) $ \(&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt;
   (k . runM :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; b p -&amp;gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; . h . fmap runM)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;on-the-run&quot;&gt;On the Run&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Conquer&lt;/code&gt; describes a calculation that we expect to be able to work with both up or down the paths of the tree. Morihata et al would probably call it a path-based decomposition. However, this presentation diverges a bit from theirs to let me vary the result type covariantly and to match up with the other foldings I've been talking about lately.&lt;/p&gt;
&lt;p&gt;Now that we can build one, we should figure out how to apply it:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; t -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k . go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap go) . divide
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To run our decomposition, we first take the input and divide it by pulling down the zipper. Then we run down the zipper recursively transforming each of the other entries in the context using the same approach, then applying (h :: D t b -&amp;gt; b) to the intermediate results. When we're all done, we polish up with whatever function we wanted to use to make the result presentable to the end-user.&lt;/p&gt;
&lt;h2 id=&quot;comonad-and-conquer&quot;&gt;&lt;a href=&quot;http://www.commandandconquer.com/en&quot;&gt;Comonad and Conquer&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Conquer&lt;/code&gt; admits many of the same instances as &lt;code&gt;M&lt;/code&gt; and &lt;code&gt;L&lt;/code&gt; from the &lt;a href=&quot;https://hackage.haskell.org/package/folds&quot;&gt;&lt;code&gt;folds&lt;/code&gt;&lt;/a&gt; package. One of the main reasons is that we assumed that the leaf was trivial. We lose a lot of structure if we don't.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;pi1&lt;/span&gt; :: !&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;pi2&lt;/span&gt; :: !&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; mempty mempty
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; c d) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (mappend a c) (mappend b d)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (f.k) h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Comonad&lt;/code&gt; is basically identical to the one for &lt;code&gt;M&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k mempty
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (k . mappend b) h) h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we get a nice &lt;code&gt;Applicative&lt;/code&gt; that can be used to fuse together multiple passes:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (const a) (const ())
  &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; kf hf &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; ka ha = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt;
    (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; bf ba) -&amp;gt; kf bf (ka ba))
    (\dab -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (hf (pi1 &amp;lt;$&amp;gt; dab)) (ha (pi2 &amp;lt;$&amp;gt; dab)))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt;@&amp;gt;) = (&amp;lt;*&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can even get a &lt;code&gt;Monad&lt;/code&gt; for rather inefficient multipass folding.&lt;/p&gt;
&lt;p&gt;Now, it isn't immediately obvious which way the &lt;code&gt;Monoid&lt;/code&gt; is used when you &lt;code&gt;duplicate&lt;/code&gt;, so lets define a couple of helper functions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;above&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;above&lt;/span&gt; t0 (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; x = go t0 &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (k . mappend x) h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap (go . divide))

&lt;span class=&quot;hljs-title&quot;&gt;below&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;below&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) t0 = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; y = go t0 &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (\x -&amp;gt; k (mappend x y)) h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap (go . divide))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These can be used to &quot;pre-apply&quot; our divide-and-conquer comonad to a prefix of our zipper &lt;code&gt;above&lt;/code&gt; or &lt;code&gt;below&lt;/code&gt; the rest of what we want to feed the fold without leaking space or holding onto anything unnecessarily.&lt;/p&gt;
&lt;h2 id=&quot;example-folding-lists&quot;&gt;Example: Folding Lists&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; [a] b = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getCons&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;} &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
  plug (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = a : &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
  walk _ = pure . &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; . getCons
  path (x:xs)   = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x, xs)
  path []       = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;sumList&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sumList&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; getSum (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; . getCons)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can run the summation over a list.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run sumList [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]
&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can also partially apply it&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run (run (duplicate sumList) [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]) [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]
&lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we have a zipper lying around with the rest of what we want cut out, we can pre-apply it:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run (above (divide [1,2,3]) sumList) [4,5]
15
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;putting-it-to-work&quot;&gt;Putting it to Work&lt;/h2&gt;
&lt;p&gt;It isn't immediately obvious that there are many algorithms that you can resolve this way.&lt;/p&gt;
&lt;p&gt;Most of the time when we're talking about tree calculations we're talking about some kind of synthesized or inherited attribute. So what kinds of things can be implemented both ways?&lt;/p&gt;
&lt;p&gt;Let's move to another example, so we can finally get some interesting structure:&lt;/p&gt;
&lt;h2 id=&quot;example-folding-trees&quot;&gt;Example: Folding Trees&lt;/h2&gt;
&lt;img alt=&quot;Illustration from Conquering Folds&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/bc69c34cda5d-folding-trees.jpg&quot;&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) b = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b | &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; b a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;

  plug (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a r) l = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r
  plug (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; l a) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r

  walk f (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a &amp;lt;$&amp;gt; f b
  walk f (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; b a) = (`&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt;` a) &amp;lt;$&amp;gt; f b

  path (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a r, l)
  path &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;path&lt;/code&gt; has to pick something, so here we just lean to the left.&lt;/p&gt;
&lt;p&gt;Analogous to our &lt;code&gt;sumList&lt;/code&gt;, we can define&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;sumTree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;sumTree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; getSum $ \ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (a + b)
  &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; b) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (a + b)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run sumTree (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;)
&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To give ourselves some non-trivial examples, lets define&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unfoldTree&lt;/span&gt; :: (s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (s, a, s)) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unfoldTree&lt;/span&gt; f s = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (l, a, r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (unfoldTree f l) a (unfoldTree f r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To help cut them off:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; _   = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; n &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; n (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (takeTree (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) l) a (takeTree (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can define a nice infinite tree that contains all of the (positive) rationals.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;sternBrocot&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rational&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sternBrocot&lt;/span&gt; = unfoldTree
  (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (a+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) b, a % b, &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a (b+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)))
  (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;img alt=&quot;Illustration from Conquering Folds&quot; loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/cf56a311dc62-SternBrocotTree.svg&quot;&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run sumTree $ takeTree &lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt; sternBrocot
&lt;span class=&quot;hljs-number&quot;&gt;26859127&lt;/span&gt; % &lt;span class=&quot;hljs-number&quot;&gt;5544&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is a fun exercise to &lt;code&gt;Conquer&lt;/code&gt; a search through the &lt;a href=&quot;http://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree&quot;&gt;Stern-Brocot tree&lt;/a&gt; for a given positive &lt;code&gt;Rational&lt;/code&gt;. They are all in there, so you'll find it eventually, but the tree goes on forever in all directions.&lt;/p&gt;
&lt;p&gt;So what can we compute that isn't just the usual &lt;code&gt;Foldable&lt;/code&gt; fare? After all we could just run through a tree left to right in-order, and answer &lt;code&gt;sum&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;How about the maximum path weight?&lt;/p&gt;
&lt;p&gt;We can compute the maximum path weight top to bottom and bottom to top, so a &lt;code&gt;Monoid&lt;/code&gt; for it should exist, by the third homomorphism theorem... and indeed it does!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mpw&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;mpw&lt;/span&gt; = conquer k h m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a _) = a
  h (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; n m) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (n + k m) n
  h (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; m n) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (n + k m) n
  m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m1 w1) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m2 w2) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (max m1 (w1 + m2)) (w1 + w2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&amp;gt;&amp;gt;&amp;gt; run mpw (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))
&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, we can compute the height of the tree. (Note: this version fixes a bug in the paper by Morihata et al.)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;height&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;height&lt;/span&gt; = conquer k h m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a _) = a + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  h (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; n m) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (k m) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  h (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; m n) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (k m) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m1 w1) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m2 w2) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (max m1 (w1 + m2)) (w1 + w2)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting It All Together&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ExistentialQuantification #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ScopedTypeVariables #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleContexts #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Parallel.Strategies
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List (&lt;span class=&quot;hljs-title&quot;&gt;unfoldr&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Proxy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Ratio
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Reflection (&lt;span class=&quot;hljs-title&quot;&gt;reify&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Reifies(..)&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t :: * -&amp;gt; *&lt;/span&gt;
  plug   :: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t -&amp;gt; t -&amp;gt; t
  walk   :: &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t b)
  path :: t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t, t)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap = fmapDefault
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap = foldMapDefault
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse = walk

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t = [&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t t]&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;divide&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t
&lt;span class=&quot;hljs-title&quot;&gt;divide&lt;/span&gt; = unfoldr path

&lt;span class=&quot;hljs-title&quot;&gt;zipped&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; t -&amp;gt; t
&lt;span class=&quot;hljs-title&quot;&gt;zipped&lt;/span&gt; dt t = &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.foldr plug t dt

&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; t -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;run&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k . go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap go) . divide
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE run #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;runPar&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; t -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runPar&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k . go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . (`using` parTraversable rseq) . fmap go) . divide
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE runPar #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;above&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;above&lt;/span&gt; t0 (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; x = go t0 &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (k . mappend x) h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap (go . divide))
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE above #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;below&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;below&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) t0 = &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; y = go t0 &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (\x -&amp;gt; k (mappend x y)) h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . fmap (go . divide))
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE below #-}&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a p = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; p (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; $ snd $ reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; $ fst (reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p)) a b

&lt;span class=&quot;hljs-title&quot;&gt;conquer&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; t a b. &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; (b -&amp;gt; a) -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; t b -&amp;gt; b) -&amp;gt; (b -&amp;gt; b -&amp;gt; b) -&amp;gt; b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a
&lt;span class=&quot;hljs-title&quot;&gt;conquer&lt;/span&gt; k h m z = reify (m,z) $ \(&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; p) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt;
   (k . runM :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; b p -&amp;gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; . h . fmap runM)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * The Main Attraction&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a = forall b. &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; b =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Instances&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;pi1&lt;/span&gt; :: !&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;pi2&lt;/span&gt; :: !&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; mempty mempty
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; c d) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (mappend a c) (mappend b d)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (f.k) h
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k mempty
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (k . mappend b) h) h
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt;@&amp;gt;) = (&amp;lt;*&amp;gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (const a) (const ())
  &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; kf hf &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; ka ha = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt;
    (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; bf ba) -&amp;gt; kf bf (ka ba))
    (\dab -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (hf (pi1 &amp;lt;$&amp;gt; dab)) (ha (pi2 &amp;lt;$&amp;gt; dab)))

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Naturals&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;&lt;/span&gt;
  plug &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt;
  walk _ &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; = pure &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;
  path (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;, n)
  path &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;     = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;nat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;nat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; getSum (\&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Lists&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; [a] b = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getCons&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;} &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
  plug (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = a : &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
  walk _ = pure . &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; . getCons
  path (x:xs)   = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x, xs)
  path []       = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;sumList&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sumList&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; getSum (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; . getCons)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Trees&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a)
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) b = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b | &lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; b a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;

  plug (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a r) l = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r
  plug (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; l a) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r

  walk f (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a &amp;lt;$&amp;gt; f b
  walk f (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; b a) = (`&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt;` a) &amp;lt;$&amp;gt; f b

  path (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a r, l)
  path &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;unfoldTree&lt;/span&gt; :: (s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (s, a, s)) -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unfoldTree&lt;/span&gt; f s = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (l, a, r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (unfoldTree f l) a (unfoldTree f r)

&lt;span class=&quot;hljs-title&quot;&gt;sternBrocot&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rational&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sternBrocot&lt;/span&gt; = unfoldTree (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (a+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) b, a % b, &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a (b+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;))) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; _   = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; n &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;takeTree&lt;/span&gt; n (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l a r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (takeTree (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) l) a (takeTree (n-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) r)

&lt;span class=&quot;hljs-title&quot;&gt;sumTree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;sumTree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; getSum h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  h (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; b)) = &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (a + b)
  h (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; b) a) = &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (a + b)

&lt;span class=&quot;hljs-title&quot;&gt;mpw&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;mpw&lt;/span&gt; = conquer k h m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a _) = a
  h (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; n m) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (n + k m) n
  h (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; m n) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (n + k m) n
  m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m1 w1) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m2 w2) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (max m1 (w1 + m2)) (w1 + w2)
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE mpw #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;height&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;height&lt;/span&gt; = conquer k h m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a _) = a + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  h (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; n m) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (k m) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  h (&lt;span class=&quot;hljs-type&quot;&gt;R&lt;/span&gt; m n) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (k m) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  m (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m1 w1) (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; m2 w2) = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (max m1 (w1 + m2)) (w1 + w2)
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE height #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  print $ run height &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
  print $ run height (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))
  print $ run ((/) &amp;lt;$&amp;gt; mpw &amp;lt;*&amp;gt; sumTree) (takeTree &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; sternBrocot)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;go-and-make-it-fast&quot;&gt;Go And Make It Fast&lt;/h2&gt;
&lt;p&gt;Now, my challenge to you is to find a nice way to execute this in parallel.&lt;/p&gt;
&lt;p&gt;The obvious approach sparks way too much.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runPar&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Recursive&lt;/span&gt; t =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; t a -&amp;gt; t -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runPar&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Conquer&lt;/span&gt; k h) = k . go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go = foldMap (h . (`using` parTraversable rseq) . fmap go) . divide
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perhaps Morihata and Matsuzaki's 2008 &lt;a href=&quot;http://www.keisu.t.u-tokyo.ac.jp/research/techrep/data/2008/METR08-27.pdf&quot;&gt;A Parallel Tree Contraction Algorithm
on Non-Binary Trees&lt;/a&gt; may serve as a guide for how to speed this up.&lt;/p&gt;
&lt;p&gt;Thoughts?&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 13, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/conquering-folds/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Parallel and Incremental CRCs</title><link>https://comonad.com/reader/2013/parallel-crc/</link><guid isPermaLink="false">https://comonad.com/reader/2013/parallel-crc/</guid><pubDate>Wed, 11 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 11 September 2013&lt;/p&gt;&lt;p&gt;Back in the &lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/&quot;&gt;second part&lt;/a&gt; of my &lt;a href=&quot;https://comonad.com/reader/series/cellular-automata/&quot;&gt;series on cellular automata&lt;/a&gt;, I implemented a &lt;a href=&quot;http://en.wikipedia.org/wiki/Moore_machine&quot;&gt;Moore machine&lt;/a&gt; for computing a &lt;a href=&quot;http://en.wikipedia.org/wiki/Cyclic_redundancy_check&quot;&gt;CRC-32&lt;/a&gt;. It was used to generate the CRC-32 for the end of a &lt;a href=&quot;http://www.libpng.org/pub/png/&quot;&gt;PNG&lt;/a&gt; block header.&lt;/p&gt;
&lt;p&gt;At the time I was somewhat saddened by the fact that I was forced to turn to a left fold, because there didn't appear to be an algorithm for computing a CRC in parallel or incrementally, beyond simply working a few more bits at a time through a lookup table.&lt;/p&gt;
&lt;p&gt;It finally occurred to me how we can implement a parallel/incremental CRC calculator today during the walk home from work, and I figured I should share it. This has a number of practical applications, as it permits us to regenerate CRCs in response to small edits in very large datasets in logarithmic time!&lt;/p&gt;
&lt;p&gt;I've never seen this algorithm before applied to CRCs, so it is at least new to me.&lt;/p&gt;
&lt;p&gt;This may also let me play some games with fast composable hashing for data structures in a later post.&lt;/p&gt;
&lt;h2 id=&quot;crc-32&quot;&gt;CRC-32&lt;/h2&gt;
&lt;p&gt;Calculating a CRC is just an exercise in long division.&lt;/p&gt;
&lt;p&gt;The particular number system we're working in is a bit peculiar.&lt;/p&gt;
&lt;p&gt;But other than that, it really is just what you were taught in grade-school!&lt;/p&gt;
&lt;p&gt;Probably the best explanation for how a CRC works comes from Ross William's rather unassuming and seemingly immortal 1996 &lt;a href=&quot;http://www.repairfaq.org/filipg/LINK/F_crc_v31.html&quot;&gt;&quot;A Painless Guide to CRC Error Detection Algorithms&quot;&lt;/a&gt;, which goes through from soup to nuts how a CRC is defined from an operational perspective. It can be found on Filip G's &lt;a href=&quot;http://www.repairfaq.org/filipg/&quot;&gt;site on repairfaq.org&lt;/a&gt;, which will provide you a fresh reminder of what the internet was like for us in the mid 90s.&lt;/p&gt;
&lt;p&gt;The content, however, is excellent.&lt;/p&gt;
&lt;h2 id=&quot;the-view-from-the-left&quot;&gt;The View from the Left&lt;/h2&gt;
&lt;p&gt;Recall my definition of CRC-32 from last time along with enough of an implementation of left folding to run it:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ExistentialQuantification, OverloadedStrings #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.ByteString.Lazy.Char8 ()
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; b a = forall x. &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;runL&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; xbx x xa) bs = xa (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.foldl' xbx x bs)

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; step &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; complement &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
     `xor` crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ runL crc32 &lt;span class=&quot;hljs-string&quot;&gt;&quot;12345689&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is already what is somewhat embarassingly considered the &quot;parallel&quot; algorithm for computing a CRC. It computes 8 bits of the CRC at a time by using a look-up table, but it doesn't let me put extra cores to work and it doesn't let me split up my workload.&lt;/p&gt;
&lt;p&gt;The algorithm I used above as the left fold can be seen as an implementation of the reflected table-driven algorithm Williams defines in Chapter 12, but it is pretty standard, modulo the trappings I've put on it to treat it as a fold, and algorithms just like it can be found everywhere.&lt;/p&gt;
&lt;p&gt;I was skimming &lt;a href=&quot;http://sar.informatik.hu-berlin.de/research/publications/SAR-PR-2006-05/SAR-PR-2006-05_.pdf&quot;&gt;Reversing CRC, Theory and Practice&lt;/a&gt; when it clicked for me what the properties are of a CRC that make this possible, so through the rest of the post, I'll try to follow their vocabulary when it comes to a CRC.&lt;/p&gt;
&lt;h2 id=&quot;tearing-apart-a-crc&quot;&gt;Tearing Apart a CRC&lt;/h2&gt;
&lt;p&gt;Let's define &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(a) = r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to be the core calculation that performs the polynomial division in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;G&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;32&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{GF}(2^{32})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; that drives a CRC. We'll abuse notation, and permit us to have partially applied this long division to have obtained some remainder &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; so far, and take &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(r,a) = r'&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to be the calculation that picks up with remainder &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and accepts more input &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, obtaining the new remainder &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r'&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Using juxtaposition in the input argument to denote concatenation, this gives us the first property we'll need:&lt;/p&gt;
&lt;div class=&quot;math-derivation&quot; data-original-text=&quot;crc(r,ab) = crc(crc(r,a),b)
&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(r,ab) = \operatorname{crc}(\operatorname{crc}(r,a),b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;If we try to adapt it directly to get a &lt;code&gt;Monoid&lt;/code&gt; we get stuck. This seems to be inherently sequential.&lt;/p&gt;
&lt;p&gt;So, let's define the Galois field used for CRC-32.&lt;/p&gt;
&lt;p&gt;When working with numbers in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;G&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;32&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{GF}(2^{32})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; addition is given by &lt;code&gt;xor&lt;/code&gt;, and multiplication is limited to like powers of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. If we fix the CRC polynomial and work bit reversed, we get the following number type.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GeneralizedNewtypeDeriving #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runGF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- -- x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | compute x * p(x)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit c &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; poly &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = xor
  (-) = xor
  _ * &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  a * b = xtimes a * unsafeShiftL b &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit b &lt;span class=&quot;hljs-number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  negate = id
  abs = id
  signum = fromIntegral . signum . runGF
  fromInteger i
    | odd i     = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x80000000&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- x^0&lt;/span&gt;
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;          &lt;span class=&quot;hljs-comment&quot;&gt;-- 0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It compiles, so it is obviously correct.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we're working bit reversed, the coefficient of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;31&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^{31}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;31&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is the least significant bit, and on the other extreme the coefficient of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 = x^0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is our most significant bit.&lt;/p&gt;
&lt;p&gt;The next most significant bit gives us &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; itself.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x40000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;xtimes&lt;/code&gt; above was the more humorously named &lt;code&gt;go&lt;/code&gt; calculation used in &lt;code&gt;crcs&lt;/code&gt; in the original left fold. It computes &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x \cdot p(x)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4445em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; for a polynomial &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;p&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. In the multiplication algorithm above, we're using it in a peasant multiplier. Since we have a working &lt;code&gt;Num&lt;/code&gt;, we can now use the built-in &lt;code&gt;(^)&lt;/code&gt; from the Prelude to compute &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;If you care about efficiency you could write the peasant exponentiator by hand:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | peasant exponentiation&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xpow&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xpow&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xpow&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; = x
&lt;span class=&quot;hljs-title&quot;&gt;xpow&lt;/span&gt; n = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; divMod n &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  (q,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) -&amp;gt;          square (xpow q)
  (q,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) -&amp;gt; xtimes $ square (xpow q)
  _     -&amp;gt; error &lt;span class=&quot;hljs-string&quot;&gt;&quot;unimplemented: extended Euclidean algorithm&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; square a = a * a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has the benefit that it gets to use &lt;code&gt;xtimes&lt;/code&gt; rather than &lt;code&gt;(* x)&lt;/code&gt; internally, shaving a few cycles, but clutters exposition. That said, if you care about efficiency, perhaps you can find me a nicer multiplication routine. The peasant exponentiator we're using isn't the fastest form of multiplication in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;G&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{GF}(2^n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. We might consider adapting something like &lt;a href=&quot;http://www.csd.uwo.ca/~eschost/Exam/Koc.pdf&quot;&gt;Montgomery multiplication and exponentiation&lt;/a&gt;, for very large choices of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, there are other multiplication routines as well.&lt;/p&gt;
&lt;p&gt;My implementation of &lt;code&gt;GF&lt;/code&gt; is structured along the lines of a quickly dashed off sketch by Adrian Keet during a discussion on &lt;code&gt;#haskell-lens&lt;/code&gt;. Any errors introduced in the above code, however, are all mine.&lt;/p&gt;
&lt;h2 id=&quot;properties-of-all-crcs&quot;&gt;Properties of all CRCs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Andrew_S._Tanenbaum&quot;&gt;Tanenbaum&lt;/a&gt;'s &lt;a href=&quot;http://www.amazon.com/Computer-Networks-Edition-Andrew-Tanenbaum/dp/0132126958&quot;&gt;Computer Networks&lt;/a&gt; describes a few of the conditions necessary to define a good polynomial, including resistance to single and two bit errors, odd numbers of bits, bursts of all ones or zeroes, etc. But even with a well chosen standard polynomial in hand, there are a couple of classes of errors that standard CRC algorithms are tweaked to handle better.&lt;/p&gt;
&lt;p&gt;Rather than reason about this through properties of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;G&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;32&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{GF}(2^{32})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; directly, let's talk about two properties that are commonly seen as weaknesses of CRC and use them to derive an algorithm.&lt;/p&gt;
&lt;h2 id=&quot;zero-blindness&quot;&gt;Zero Blindness&lt;/h2&gt;
&lt;p&gt;An actual CRC looks like &lt;code&gt;CRC(a) = crc(INIT,a) `xor` FINAL&lt;/code&gt;, rather than being a just pure long division. Usually &lt;code&gt;INIT&lt;/code&gt; and &lt;code&gt;FINAL&lt;/code&gt; will be something like all 1s to complement the initial state and the final state. The reason why &lt;code&gt;INIT&lt;/code&gt; is chosen to be non-zero is to combat a phenomenon known as &quot;zero blindness&quot;.&lt;/p&gt;
&lt;p&gt;If you consider a CRC as a polynomial long division, then prefixing a number of zeroes onto the number we're dividing wouldn't change the CRC at all! So what is done in practice is that we start with a current &quot;remainder&quot; that is &lt;code&gt;0xffffffff&lt;/code&gt; rather than &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is another kind of zero blindness that affects the message followed by the CRC itself, any additional trailing 0's wouldn't affect the checksum, so most real world CRCs &lt;code&gt;complement&lt;/code&gt; all of the bits of the remainder before emitting it into the output as well.&lt;/p&gt;
&lt;p&gt;Here we'll be using the same mask for both &lt;code&gt;INIT&lt;/code&gt; and &lt;code&gt;FINAL&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^31 + x^30 + ... + x + 1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll be reasoning about our CRC by conceptually abusing this property of a CRC alongside a second, much more powerful property. 'forcing' our CRC into a blind state by exploiting:&lt;/p&gt;
&lt;h2 id=&quot;additive-homomorphism&quot;&gt;Additive Homomorphism&lt;/h2&gt;
&lt;p&gt;This second property is one that is much more often used from a cracking perspective than as a desirable property:&lt;/p&gt;
&lt;div class=&quot;math-derivation&quot; data-original-text=&quot;crc(r1 `xor` r2, a1 `xor` a2) = crc(r1,a1) `xor` crc(r2,a2)
&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;x&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;x&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;x&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(r_{1} \mathbin{\mathrm{xor}} r_{2}, a_{1} \mathbin{\mathrm{xor}} a_{2}) = \operatorname{crc}(r_{1},a_{1}) \mathbin{\mathrm{xor}} \operatorname{crc}(r_{2},a_{2})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2 id=&quot;exploiting-weakness&quot;&gt;Exploiting Weakness&lt;/h2&gt;
&lt;p&gt;If we have input fragments &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with lengths &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; respectively:&lt;/p&gt;
&lt;div class=&quot;math-derivation&quot; data-original-text=&quot;CRC(ab) =                               -- definition of CRC
crc(INIT,ab) + FINAL =                  -- linearity
crc(INIT,a0^n + 0^m b) + FINAL =        -- additive homomorphism
crc(INIT,a0^n) + crc(0,0^nb) + FINAL =  -- zero blindness
crc(INIT,a0^n) + crc(0,b) + FINAL       -- definition of crc
crc(crc(INIT,a),0^n) + crc(0,b) + FINAL -- additive homomorphism
crc(crc(INIT,0^m)+crc(0,a),0^n) + crc(0,b) + FINAL
&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mtable rowspacing=&quot;0.25em&quot; columnalign=&quot;right left right left&quot; columnspacing=&quot;0em 1em 0em&quot;&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;CRC&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;definition&amp;#160;of&amp;#160;CRC&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;linearity&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;additive&amp;#160;homomorphism&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;zero&amp;#160;blindness&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;definition&amp;#160;of&amp;#160;crc&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;additive&amp;#160;homomorphism&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\begin{aligned}
 &amp;amp; \operatorname{CRC}(ab) \\
{}= &amp;amp; \operatorname{crc}(\mathrm{INIT},ab) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{definition of CRC} \\
{}= &amp;amp; \operatorname{crc}(\mathrm{INIT},a0^{n} + 0^{m} b) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{linearity} \\
{}= &amp;amp; \operatorname{crc}(\mathrm{INIT},a0^{n}) + \operatorname{crc}(0,0^{n}b) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{additive homomorphism} \\
{}= &amp;amp; \operatorname{crc}(\mathrm{INIT},a0^{n}) + \operatorname{crc}(0,b) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{zero blindness} \\
{}= &amp;amp; \operatorname{crc}(\operatorname{crc}(\mathrm{INIT},a),0^{n}) + \operatorname{crc}(0,b) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{definition of crc} \\
{}= &amp;amp; \operatorname{crc}(\operatorname{crc}(\mathrm{INIT},0^{m})+\operatorname{crc}(0,a),0^{n}) + \operatorname{crc}(0,b) + \mathrm{FINAL} &amp;amp;&amp;amp; \text{additive homomorphism}
\end{aligned}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:10.2em;vertical-align:-4.85em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mtable&quot;&gt;&lt;span class=&quot;col-align-r&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:5.35em;&quot;&gt;&lt;span style=&quot;top:-7.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-6.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-4.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-1.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:1.49em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.85em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;col-align-l&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:5.35em;&quot;&gt;&lt;span style=&quot;top:-7.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;CRC&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-6.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-4.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-1.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:1.49em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.85em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;arraycolsep&quot; style=&quot;width:1em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;col-align-r&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:3.85em;&quot;&gt;&lt;span style=&quot;top:-5.85em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-4.35em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.85em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-1.35em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:0.15em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:1.65em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.85em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;col-align-l&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:3.85em;&quot;&gt;&lt;span style=&quot;top:-6.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;definition&amp;#160;of&amp;#160;CRC&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-4.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;linearity&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;additive&amp;#160;homomorphism&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-1.51em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;zero&amp;#160;blindness&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.01em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;definition&amp;#160;of&amp;#160;crc&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:1.49em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;additive&amp;#160;homomorphism&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.85em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;That final expression requires us to be able to calculate &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(r,0^m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and to know &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(0,a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; for each half of the input, but nothing more.&lt;/p&gt;
&lt;p&gt;As James Deikun pointed out to me, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(r,0^m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is particularly well behaved. When we look at what it does to our division is it appends just a number of 0's. When we work out the effect on the remainder we just need to multiply through our remainder by &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;!&lt;/p&gt;
&lt;p&gt;Instead of storing the string &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0^m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or the length &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, I'll just store &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; directly.&lt;/p&gt;
&lt;p&gt;Monoidal composition proceeds through a simplification of the definition above, where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;F&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{INIT} = \mathrm{FINAL} = 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;FINAL&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;math-derivation&quot; data-original-text=&quot;crc(0,ab) =                    -- linearity
crc(0,a 0^n + 0^mb)            -- additive homomorphism
crc(0,a 0^n) + crc(0,0^m b) =  -- zero blindness
crc(0,a 0^n) + crc(0,b) =      -- definition of crc
crc(crc(0,a),0^n) + crc(0,b) = -- crc(r,0^m) = r*x^m
crc(0,a)*x^n + crc(0,b)
&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mtable rowspacing=&quot;0.25em&quot; columnalign=&quot;right left right left&quot; columnspacing=&quot;0em 1em 0em&quot;&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;linearity&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;additive&amp;#160;homomorphism&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;zero&amp;#160;blindness&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mtext&gt;definition&amp;#160;of&amp;#160;crc&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\begin{aligned}
 &amp;amp; \operatorname{crc}(0,ab) \\
{}= &amp;amp; \operatorname{crc}(0,a 0^{n} + 0^{m}b) &amp;amp;&amp;amp; \text{linearity} \\
{}= &amp;amp; \operatorname{crc}(0,a 0^{n}) + \operatorname{crc}(0,0^{m} b) &amp;amp;&amp;amp; \text{additive homomorphism} \\
{}= &amp;amp; \operatorname{crc}(0,a 0^{n}) + \operatorname{crc}(0,b) &amp;amp;&amp;amp; \text{zero blindness} \\
{}= &amp;amp; \operatorname{crc}(\operatorname{crc}(0,a),0^{n}) + \operatorname{crc}(0,b) &amp;amp;&amp;amp; \text{definition of crc} \\
{}= &amp;amp; \operatorname{crc}(0,a)\cdot x^{n} + \operatorname{crc}(0,b) &amp;amp;&amp;amp; \operatorname{crc}(r,0^{m}) = r\cdot x^{m}
\end{aligned}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:8.7em;vertical-align:-4.1em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mtable&quot;&gt;&lt;span class=&quot;col-align-r&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.6em;&quot;&gt;&lt;span style=&quot;top:-6.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-5.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:0.74em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.1em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;col-align-l&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.6em;&quot;&gt;&lt;span style=&quot;top:-6.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-5.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:0.74em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.1em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;arraycolsep&quot; style=&quot;width:1em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;col-align-r&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:3.1em;&quot;&gt;&lt;span style=&quot;top:-5.1em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.6em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.1em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.6em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:0.9em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.84em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.1em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;col-align-l&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:3.1em;&quot;&gt;&lt;span style=&quot;top:-5.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;linearity&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;additive&amp;#160;homomorphism&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-2.26em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;zero&amp;#160;blindness&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-0.76em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;definition&amp;#160;of&amp;#160;crc&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:0.74em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7144em;&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:4.1em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;So if we just store the length (mangled as &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) and the CRC remainder from a starting remainder of &lt;code&gt;0&lt;/code&gt;, we can compose these answers associatively!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m `mappend` &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; q n = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (p*n+q) (m*n)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here &lt;code&gt;CRC32 p m&lt;/code&gt; stores &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;p = \operatorname{crc}(0,a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; for our input string alongside &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m = x^{|a|}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.888em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.888em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;∣&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Our &lt;code&gt;mempty&lt;/code&gt; comes from the fact that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mtext mathvariant=&quot;monospace&quot;&gt;&quot;&quot;&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(0,\text{\texttt{&quot;&quot;}}) = 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord texttt&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and note that the 1 here is actually &lt;code&gt;GF 0x80000000&lt;/code&gt; and represents &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in our Galois field, so we're denoting an input of length 0.&lt;/p&gt;
&lt;p&gt;If we build the standard byte-wise CRC table:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = listArray (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;) $ map (xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;) [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can then define the injection into our monoid for a byte worth of data at a time.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (crcs ! a) (x^&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- x^8 = GF 0x800000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last thing we need to do is apply the &lt;code&gt;INIT&lt;/code&gt; and &lt;code&gt;FINAL&lt;/code&gt; masks.&lt;/p&gt;
&lt;p&gt;Going back to our original equations, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;crc&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;N&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{crc}(\mathrm{INIT},0^m)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;crc&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;INIT&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; can be computed by multiplying the mask by &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and we can just add in the &lt;code&gt;FINAL&lt;/code&gt; mask when we're done. Here it is also &lt;code&gt;0xffffffff&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using those results we can finally find our fold:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m) = runGF (ones * m + p + ones)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/parallel-crc/&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-story-so-far&quot;&gt;The Story So Far&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# OPTIONS_GHC -fno-warn-type-defaults #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Profunctor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Array.Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runGF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;IArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | compute x * p(x)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit c &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; poly &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = xor
  (-) = xor
  _ * &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  a * b = xtimes a * unsafeShiftL b &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit b &lt;span class=&quot;hljs-number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  negate = id
  abs = id
  signum = fromIntegral . signum . runGF
  fromInteger i
    | odd i     = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x80000000&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- x^0&lt;/span&gt;
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;          &lt;span class=&quot;hljs-comment&quot;&gt;-- 0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x40000000&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- x^1&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- | x^31+x^30+...+x+1&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m `mappend` &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; q n = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (p*n+q) (m*n)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = listArray (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;) $ map (xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;) [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;]

&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m) = runGF (ones * m + p + ones)

&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (crcs ! a) (x^&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ runCRC $ foldMap (byte.fromIntegral.fromEnum) &lt;span class=&quot;hljs-string&quot;&gt;&quot;123456789&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;deeper-down-the-rabbit-hole&quot;&gt;Deeper Down the Rabbit Hole&lt;/h2&gt;
&lt;p&gt;This also means if you keep the blinded CRCs around you can calculate a modified aggregate CRC without starting over from the left of your document or ADT.&lt;/p&gt;
&lt;p&gt;Combining this with a &lt;a href=&quot;http://www.soi.city.ac.uk/~ross/papers/FingerTree.html&quot;&gt;finger tree&lt;/a&gt; can enable you to calculate a CRC for an entire document in parallel and then to update it incrementally in mere logarithmic time in response to edits. It also means that you do not need to invalidate an entire CRC.&lt;/p&gt;
&lt;p&gt;Combining this with an ADT makes for cheap rehashing as portions of a structure changes.&lt;/p&gt;
&lt;p&gt;Nothing here was specific to the modulus used for CRC-32. It works equally well for any other standard &quot;Rocksoft&quot;-style CRC. This works particularly well for the variant of CRC-8 used in &lt;a href=&quot;http://en.wikipedia.org/wiki/Advanced_Encryption_Standard&quot;&gt;Rijndael/AES&lt;/a&gt;, because the lookup table can be used directly for multiplication.&lt;/p&gt;
&lt;p&gt;A CRC isn't a cryptographically strong hash, however, due to their importance in network protocols, telecommunications, document and image formats,  and general ubiquity, having a way to compute them both in parallel and incrementally opens up new opportunities.&lt;/p&gt;
&lt;p&gt;Now what we've come all the way through to the conclusion there are obvious analogies to how one can execute a Rabin-Karp or a simple addition modulo prime hash in parallel.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/parallel-crc/&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;details class=&quot;incremental-detail&quot;&gt;&lt;summary&gt;Using associativity to update a cached tree&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/parallel-crc/&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&quot;monoidal-folding&quot;&gt;Monoidal Folding&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(if you aren't interested in folding, you can probably skip the remainder, but it does polish up the API nicely)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I haven't mentioned a single &lt;code&gt;Comonad&lt;/code&gt; all post. Time to fix that.&lt;/p&gt;
&lt;p&gt;We can build up a new kind of folding, based capturing the arguments to a &lt;code&gt;foldMap&lt;/code&gt; in amber, just like &lt;a href=&quot;http://squing.blogspot.com/2008/11/beautiful-folding.html&quot;&gt;Max Rabkin originally did&lt;/a&gt; with the arguments to &lt;code&gt;foldl'&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This yields the following type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b = forall r. &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can map over the inputs and outputs:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m e) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (g.k) (h.f) m e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is also an &lt;code&gt;Applicative&lt;/code&gt; structured just like the &lt;code&gt;Applicative&lt;/code&gt; for &lt;code&gt;L&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is even a &lt;code&gt;Monad&lt;/code&gt; that permits you to write (inefficient) multipass algorithms!&lt;/p&gt;
&lt;h2 id=&quot;pause-for-reflection&quot;&gt;Pause for Reflection&lt;/h2&gt;
&lt;p&gt;The problem then becomes, how to run it. &lt;code&gt;foldMap&lt;/code&gt; doesn't let us explicitly pass arguments for the &lt;code&gt;mappend&lt;/code&gt; and &lt;code&gt;mempty&lt;/code&gt; of the Monoid in question.&lt;/p&gt;
&lt;p&gt;We could run &lt;code&gt;M&lt;/code&gt; using &lt;code&gt;foldr&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) xs = k (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;.foldr (m.h) z xs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But that isn't very satisfying, the whole point of introducing a 'Monoid' was to be able to associate however we pleased.&lt;/p&gt;
&lt;p&gt;We could make a &lt;code&gt;Monoid&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runSlow&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; (\_ e -&amp;gt; e)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; f) (&lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; g) = &lt;span class=&quot;hljs-type&quot;&gt;Slow&lt;/span&gt; $ \p e = runSlow f p e `p` runShow g p e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if you have any sharing of monoidal values, then working with &lt;code&gt;Slow&lt;/code&gt; will actually only share the &lt;em&gt;functions&lt;/em&gt; it contains, not their results.&lt;/p&gt;
&lt;p&gt;The better tool for evaluating &lt;code&gt;M&lt;/code&gt;, unfortunately requires some heavy lifting. We can turn to my &lt;code&gt;reflection&lt;/code&gt; package to allow us to manufacture a &lt;code&gt;Monoid&lt;/code&gt; out of an arbitrary function and unit value.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/thoughtpolice&quot;&gt;Austin Seipp&lt;/a&gt; recently wrote &lt;a href=&quot;https://www.fpcomplete.com/user/thoughtpolice/using-reflection&quot;&gt;a nice tutorial on how to do this&lt;/a&gt;, so I'll just skip to the solution:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; a s = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runN&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; s (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; $ snd $ reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; $ fst (reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s)) a b

&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m (z :: m)) s = reify (m, z) $
    \ (_ :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s) -&amp;gt; k $ runN (foldMap (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; #. h) s :: &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; m s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we make up a &lt;code&gt;Monoid&lt;/code&gt; that reflects how to do what it needs to do out of the environment, then make up an instance with the &lt;code&gt;mappend&lt;/code&gt; and &lt;code&gt;mempty&lt;/code&gt; we want.&lt;/p&gt;
&lt;p&gt;Finally &lt;code&gt;(#.)&lt;/code&gt; in &lt;code&gt;runM&lt;/code&gt; is drawn from &lt;code&gt;Data.Profunctor.Unsafe&lt;/code&gt; to work around the fact that &lt;code&gt;SomeNewType . f&lt;/code&gt; doesn't erase down to &lt;code&gt;f&lt;/code&gt;, but rather to the eta-expansion of &lt;code&gt;f&lt;/code&gt;, so it has ever so slightly different semantics.&lt;/p&gt;
&lt;p&gt;Now that we can run an monoidal folding, it'd be nice to be able to do the same things we could with left foldings.&lt;/p&gt;
&lt;h2 id=&quot;not-the-comonads-you-are-looking-for&quot;&gt;Not The Comonads You Are Looking For&lt;/h2&gt;
&lt;p&gt;But if we go to copy the &lt;code&gt;Comonad&lt;/code&gt; from &lt;code&gt;L&lt;/code&gt; we get gobbledygook!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; k _ z) = k z
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; k h z) = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; k h) h z
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we were working with &lt;code&gt;L&lt;/code&gt;, this comonad was able to sneak in before the final tweak is applied at the end and snatches up the seed we've computed so far and uses at as the seed for the nested &lt;code&gt;L&lt;/code&gt; in&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;duplicate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; a b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if we do that with &lt;code&gt;M&lt;/code&gt;, we'd get something that replaced the &lt;code&gt;mempty&lt;/code&gt; of our &lt;code&gt;Monoid&lt;/code&gt; with the result of what we've tallied up so far!&lt;/p&gt;
&lt;p&gt;Last time, we used the fact that &lt;code&gt;(L a)&lt;/code&gt; was isomorphic to an &lt;code&gt;EnvT&lt;/code&gt;'d &lt;code&gt;Store&lt;/code&gt; &lt;code&gt;Comonad&lt;/code&gt;, where we'd quantified away the state parameter.&lt;/p&gt;
&lt;p&gt;This time, we'll have to turn to a different isomorphism.&lt;/p&gt;
&lt;p&gt;There is a comonad for &lt;code&gt;(-&amp;gt;) m&lt;/code&gt;, whenever &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a &lt;code&gt;Monoid&lt;/code&gt;. This &lt;code&gt;Comonad&lt;/code&gt; is what I called the &lt;code&gt;Traced&lt;/code&gt; comonad in &lt;code&gt;comonad-transformers&lt;/code&gt;. If you squint hard enough, you can see that &lt;code&gt;M a&lt;/code&gt; is isomorphic to &lt;code&gt;forall m. Monoid m =&amp;gt; EnvT (a -&amp;gt; m) ((-&amp;gt;) m) a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When we borrow this structure we get&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k _ _ z) = k z
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (\n -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (k . m n) h m z) h m z
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;isomorphism-does-not-imply-equal-efficiency&quot;&gt;Isomorphism Does Not Imply Equal Efficiency&lt;/h2&gt;
&lt;p&gt;I had a performance issue with the monoid homomorphism described in the last post, that this &lt;code&gt;Comonad&lt;/code&gt; helps address.&lt;/p&gt;
&lt;p&gt;Last time I noted that with &lt;code&gt;L&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; = more []
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; xs =&amp;lt;= more ys = more (xs ++ ys)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if we expand the second law:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; (xs ++ ys) = more xs =&amp;lt;= more ys = more xs . extend (more ys)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;there we're partially applying a &lt;em&gt;suffix&lt;/em&gt; of our input to a left fold!&lt;/p&gt;
&lt;p&gt;This means we're capturing it in the environment:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; xs . extend (more ys) = more xs . fmap (more ys) . duplicate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This leads to the observation that we don't have to do that, our comonad was set up precisely so we could partially evaluate out to a new seed.&lt;/p&gt;
&lt;p&gt;By naturality or good old fashioned equational reasoning, we can get to an alternate statement of the second law:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; (xs ++ ys) = more ys . more xs . duplicate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us an efficient algorithm for composing left foldings.&lt;/p&gt;
&lt;p&gt;When we work with the monoidal folding above, we have the flexibility to get the more efficient non-leaky version for both the left side and the right side of the structure.&lt;/p&gt;
&lt;h2 id=&quot;putting-it-back-together-again&quot;&gt;Putting It Back Together Again&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, ScopedTypeVariables, FlexibleContexts, UndecidableInstances #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Profunctor.Unsafe
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Proxy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Reflection
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Array.Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runGF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;IArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;poly&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- the polynomial we're working modulo in GF(2^32) for CRC32.&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | compute x * p(x)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit c &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; poly &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = xor
  (-) = xor
  _ * &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  a * b = xtimes a * unsafeShiftL b &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit b &lt;span class=&quot;hljs-number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  negate = id
  abs = id
  signum = fromIntegral . signum . runGF
  fromInteger i
    | odd i     = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x80000000&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- x^0&lt;/span&gt;
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;          &lt;span class=&quot;hljs-comment&quot;&gt;-- 0&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x40000000&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^31 + x^30 + ... + x + 1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ones&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m `mappend` &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; q n = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (p*n+q) (m*n)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = listArray (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;) $ map (xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;) [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;]

&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;runCRC&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; p m) = runGF (ones * m + p + ones)

&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;byte&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;CRC32&lt;/span&gt; (crcs ! a) (x^&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; :: (r -&amp;gt; b) -&amp;gt; (a -&amp;gt; r) -&amp;gt; (r -&amp;gt; r -&amp;gt; r) -&amp;gt; r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (f.k) h m z
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (g.k) (h.f) m z
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k _ _ z) = k z
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (\n -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (k . m n) h m z) h m z

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; a s = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runN&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; s (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; $ snd $ reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s)
  mappend (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; $ fst (reflect (&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s)) a b

&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m (z :: m)) s = reify (m, z) $
    \ (_ :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s) -&amp;gt; k $ runN (foldMap (&lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; #. h) s :: &lt;span class=&quot;hljs-type&quot;&gt;N&lt;/span&gt; m s)

&lt;span class=&quot;hljs-title&quot;&gt;runR&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runR&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) xs = k (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;.foldr (m.h) z xs)

&lt;span class=&quot;hljs-title&quot;&gt;runL&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) xs = k (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;.foldl' (\r -&amp;gt; m r . h) z xs)

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; runCRC byte mappend mempty

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ runM crc32 [&lt;span class=&quot;hljs-number&quot;&gt;0x12&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0x34&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the only part of the CRC API that the user has to concern themselves with is the actual &lt;code&gt;crc32&lt;/code&gt; combinator. Everything else is generic and can be reused for other folds. If you want to keep folding you can keep the fold alive by using &lt;code&gt;duplicate&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;We could actually abstract over the choice of polynomial for our Galois field, by calculating our lut locally in a &lt;code&gt;crc&lt;/code&gt; combinator that was parameterized on the values of &lt;code&gt;INIT&lt;/code&gt;, &lt;code&gt;FINAL&lt;/code&gt; and &lt;code&gt;poly&lt;/code&gt;, or even by using &lt;code&gt;reflection&lt;/code&gt; to move the modulus and/or lookup table into a type parameter. By switching to &lt;code&gt;Bits&lt;/code&gt; and &lt;code&gt;Integral&lt;/code&gt; constraints rather than fixing ourselves to &lt;code&gt;Word32&lt;/code&gt;, we can implement &lt;code&gt;CRC-8&lt;/code&gt;, &lt;code&gt;CRC-16&lt;/code&gt; and &lt;code&gt;CRC-64&lt;/code&gt; variants very easily as well.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Expanded implementation&lt;/summary&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, RankNTypes, ScopedTypeVariables, StandaloneDeriving, MultiParamTypeClasses, FlexibleContexts #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# OPTIONS_GHC -fno-warn-type-defaults #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Profunctor
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Proxy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Reflection
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Array.Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runGF&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | compute x * p(x)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; s a) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s
&lt;span class=&quot;hljs-title&quot;&gt;xtimes&lt;/span&gt; c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit c &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; (reflect c) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE xtimes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = xor
  (-) = xor
  _ * &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  a * b = xtimes a * unsafeShiftL b &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; testBit b (bitSize b - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  negate = id
  abs = id
  signum = fromIntegral . signum . runGF
  fromInteger i
    | odd i     = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; (bit (bitSize (undefined :: a) - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)) &lt;span class=&quot;hljs-comment&quot;&gt;-- x^0&lt;/span&gt;
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;                     &lt;span class=&quot;hljs-comment&quot;&gt;-- 0&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a s. &lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; (bit (bitSize (undefined :: a) - &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE x #-}&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; !a !a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; p m `mappend` &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; q n = &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; (p*n+q) (m*n)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Bits&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;IArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; a) =&amp;gt; a -&amp;gt; a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;crc&lt;/span&gt; _INIT _FINAL poly = reify poly $ \(_ :: &lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; s) -&amp;gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; crcs :: &lt;span class=&quot;hljs-type&quot;&gt;UArray&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; a s)
      crcs = listArray (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;) $ map (xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.xtimes.&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt;) [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;]
      k (&lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; p m) = runGF (&lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; _INIT * m + p + &lt;span class=&quot;hljs-type&quot;&gt;GF&lt;/span&gt; _FINAL)
      h a = &lt;span class=&quot;hljs-type&quot;&gt;CRC&lt;/span&gt; (crcs ! a) (x^&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;)
  &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h mappend mempty
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE crc #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = crc &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc64_ecma182&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc64_ecma182&lt;/span&gt; = crc (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0xC96C5795D7870F42&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc8&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc8&lt;/span&gt; = crc &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xab&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc8_sae&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc8_sae&lt;/span&gt; = crc &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xb8&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; :: (r -&amp;gt; b) -&amp;gt; (a -&amp;gt; r) -&amp;gt; (r -&amp;gt; r -&amp;gt; r) -&amp;gt; r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (f.k) h m z
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (g.k) (h.f) m z
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k _ _ z) = k z
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (\n -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; (k . m n) h m z) h m z

&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;runM&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; k h m z) xs = k (&lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;.foldr (m.h) z xs)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ runM crc32 [&lt;span class=&quot;hljs-number&quot;&gt;0x12&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0x34&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;Now that the algorithm is fully assembled, I can recognize aspects of it.&lt;/p&gt;
&lt;p&gt;I've seen a similar trick applied to turn a Rabin-Karp hash into a rolling hash.&lt;/p&gt;
&lt;p&gt;There the &lt;code&gt;Monoid&lt;/code&gt; was the same, except we worked with a different ring &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;Z&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;Z&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbb{Z}/n\mathbb{Z}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;Z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, with &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; odd, and instead of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x^k&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8491em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8491em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, we track &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/msup&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;m&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;/mo&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^k \bmod n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8491em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8491em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.0556em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.0556em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and exploit the fact that 2 is coprime with n.&lt;/p&gt;
&lt;p&gt;Spotting that connection means that this also provides a way to make an efficient rolling-hash function out of any standard CRC!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 10th, 2013&lt;/p&gt;
&lt;p&gt;P.S. I packaged &lt;code&gt;M&lt;/code&gt; up over the weekend in the &lt;a href=&quot;https://hackage.haskell.org/package/folds&quot;&gt;&lt;code&gt;folds&lt;/code&gt; package on hackage&lt;/a&gt;, but I reserve the right to change the API and welcome feedback.&lt;/p&gt;
&lt;p&gt;[Edit: It appears either &lt;a href=&quot;https://crcutil.googlecode.com/hg/doc/crc.pdf&quot;&gt;Kadatch or Jenkins&lt;/a&gt; figured out the same basic trick, which isn't surprising given how basic it is once you peel apart the math. They also identified the opportunity for a CRC-based rolling hash.]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/parallel-crc/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Once</title><link>https://comonad.com/reader/2013/snippets-once/</link><guid isPermaLink="false">https://comonad.com/reader/2013/snippets-once/</guid><pubDate>Tue, 03 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 3 September 2013&lt;/p&gt;&lt;p&gt;I wrote this fragment a few years ago and have talked about it to folks individually, but it came up again in discussion on the &lt;code&gt;#haskell&lt;/code&gt; channel, so I figured it was worth posting about in a central location.&lt;/p&gt;
&lt;h2 id=&quot;evaluating-to-normal-form&quot;&gt;Evaluating to Normal Form&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;deepseq&lt;/code&gt; package's &lt;code&gt;Control.DeepSeq&lt;/code&gt; provides the incredibly useful &lt;code&gt;NFData&lt;/code&gt; class.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NFData&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  rnf :: a -&amp;gt; ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;rnf&lt;/code&gt; evaluates its argument fully to normal form.&lt;/p&gt;
&lt;p&gt;This class is abused by efficiency afficionados everywhere to ensure that no undue laziness leaks into their data structures.&lt;/p&gt;
&lt;p&gt;However, it is easy to abuse, and often winds up having to do a lot of unnecessary work forcing things we already know to be forced!&lt;/p&gt;
&lt;h2 id=&quot;once-and-for-all&quot;&gt;Once and For All&lt;/h2&gt;
&lt;p&gt;We can prevent that by making a rather tricky little instance of &lt;code&gt;NFData&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.DeepSeq
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Copointed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; () a&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;runOnce&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runOnce&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; _ a) = a

&lt;span class=&quot;hljs-title&quot;&gt;once&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;NFData&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;once&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; (rnf a) a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NFData&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  rnf (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; () _) = ()
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; _ a) = f a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Copointed&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  copoint (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; _ a) = a

&lt;span class=&quot;hljs-title&quot;&gt;_Once&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;NFData&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Iso'&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;_Once&lt;/span&gt; = iso runOnce once

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It compiled.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, anywhere you expect to spam &lt;code&gt;rnf&lt;/code&gt; in your code, just wrap the value in &lt;code&gt;Once&lt;/code&gt;, and any attempts will only force the fragment underneath once.&lt;/p&gt;
&lt;p&gt;This can make a massive difference in the performance of code that happens to abuse &lt;code&gt;rnf&lt;/code&gt;, enabling it to avoid doing useless work and avoid thrashing caches walking over irrelevant data.&lt;/p&gt;
&lt;p&gt;You don't have to use &lt;code&gt;Once&lt;/code&gt; to make this trick work. You can of course put extra &lt;code&gt;()&lt;/code&gt; arguments as needed recursively within your data structure and replicate the &lt;code&gt;NFData&lt;/code&gt; trick above yourself.&lt;/p&gt;
&lt;h2 id=&quot;with-a-little-bit-of-lens&quot;&gt;With A Little Bit of Lens&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;lens&lt;/code&gt; you can collapse the entire API for working with &lt;code&gt;Once&lt;/code&gt; to a single isomorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;_Once&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;NFData&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Iso'&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Once&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;_Once&lt;/span&gt; = iso runOnce once
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 3, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/snippets-once/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Mandelbrot</title><link>https://comonad.com/reader/2013/snippets-mandelbrot/</link><guid isPermaLink="false">https://comonad.com/reader/2013/snippets-mandelbrot/</guid><pubDate>Mon, 02 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 2 September 2013&lt;/p&gt;&lt;p&gt;This short little snippet combines a Mandelbrot set generator using lens based on one by &lt;a href=&quot;https://github.com/nandykins&quot;&gt;N. Haas&lt;/a&gt; with the fold-based PNG generator from the &lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/&quot;&gt;second part of my cellular automata series&lt;/a&gt;. His version of the Mandelbrot function was tighter than mine, but I mixed it with the formatting logic.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/snippets-mandelbrot/#mandelbrot-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ExistentialQuantification #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE Rank2Types #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Codec.Compression.Zlib
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.DeepSeq
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Parallel.Strategies
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary.Put
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Complex
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; F
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Mandelbrot&lt;/span&gt;


&lt;span class=&quot;hljs-title&quot;&gt;mandelbrot&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;mandelbrot&lt;/span&gt; n w h = png w h $ \r i -&amp;gt;
 maybe &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; scale $ steps $ (r/.w*&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;-&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) :+ (i/.h*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
   x /. y = fromIntegral x / fromIntegral y :: &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;
   scale k = floor (k /. n * &lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;)
   diverges (r :+ i) = r^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + i^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
   steps c = iterate (\z -&amp;gt; z^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + c) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; ^?
     taking n ifolded.filtered diverges.asIndex

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Folds&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; b a = forall x. &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; bs (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; xbx x xa) = xa (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.foldl' xbx x bs)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * CRC32&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; step &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; complement &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; `xor` crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- * PNG&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; h b = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b)
  putLazyByteString h
  putLazyByteString b
  putWord32be $ more (h &amp;lt;&amp;gt; b) crc32

&lt;span class=&quot;hljs-title&quot;&gt;putChunks&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunks&lt;/span&gt; h b = forM_ (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.toChunks b) (putChunk h . &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.fromChunks . return)

&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; w h p = runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putLazyByteString &lt;span class=&quot;hljs-string&quot;&gt;&quot;\x89PNG\r\n\x1a\n&quot;&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IHDR&quot;&lt;/span&gt; $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    putWord32be (fromIntegral w)
    putWord32be (fromIntegral h)
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 8 bit color depth&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- greyscale&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- Adam7 interlaced&lt;/span&gt;
  putChunks &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $
    compressWith defaultCompressParams { compressLevel = bestSpeed } $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IEND&quot;&lt;/span&gt; mempty
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    pass ys xs = forM_ ys $ \y -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.mapM_ put (fmap (p ?? y) xs `using` parListChunk &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; rdeepseq)


&lt;span class=&quot;hljs-comment&quot;&gt;-- * Yesod&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yesod&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;
mkYesod &quot;&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&quot; [parseRoutes| / &lt;span class=&quot;hljs-type&quot;&gt;ImageR&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GET&lt;/span&gt; |]


getImageR :: &lt;span class=&quot;hljs-type&quot;&gt;MonadHandler&lt;/span&gt; m =&amp;gt; m &lt;span class=&quot;hljs-type&quot;&gt;TypedContent&lt;/span&gt;
getImageR = sendResponse
          $ toTypedContent (&lt;span class=&quot;hljs-title&quot;&gt;typePng&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;toContent&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;img&lt;/span&gt;)
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    img = mandelbrot &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;600&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = warpEnv &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It would be fun to modify the little embedded Yesod web server to permit interactive browsing of the resulting Mandelbrot set.&lt;/p&gt;
&lt;h3 id=&quot;update-sept-2-2013-just-add-parallelism&quot;&gt;[Update: Sept 2, 2013] Just Add Parallelism&lt;/h3&gt;
&lt;p&gt;In the PNG writer, replacing&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;forM_&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] $ \x -&amp;gt; put (p x y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with a little bit of parallelism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.mapM_ put
  (fmap (p ?? y) [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] `using` parListChunk &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; rdeepseq)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rather dramatically speeds up rendering when compiled and run locally with the threaded runtime.&lt;/p&gt;
&lt;p&gt;Unfortunately, we don't seem to have the ability to pass RTS flags here on the School of Haskell at this time.&lt;/p&gt;
&lt;h3 id=&quot;update-sept-2-2013-interlacing-and-incrementalization&quot;&gt;[Update: Sept 2, 2013] Interlacing and Incrementalization&lt;/h3&gt;
&lt;p&gt;I also took the liberty of modifying the PNG writer to support directly generating the image
using greyscale to cut down repetition, and to support multiple IDAT blocks and use Adam7 interlacing so you can see the Mandelbrot set as soon as possible.&lt;/p&gt;
&lt;p&gt;Greyscaling just involves changing one of the constants in the PNG header.&lt;/p&gt;
&lt;p&gt;Getting multiple &lt;code&gt;IDAT&lt;/code&gt; blocks just involves replacing&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;putChunks&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;after we let Haskell pick for us reasonable sounding chunk boundaries:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;putChunks&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunks&lt;/span&gt; h b = forM_ (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.toChunks b) $
  putChunk h . &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.fromChunks . return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Switching to &lt;a href=&quot;http://en.wikipedia.org/wiki/Adam7_algorithm&quot;&gt;Adam7&lt;/a&gt; is only slightly more involved.&lt;/p&gt;
&lt;p&gt;After we factor out the core loop that generates our PNG body:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;    pass ys xs = forM_ ys $ \y -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.mapM_ put (fmap (p ?? y) xs `using` parListChunk &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; rdeepseq)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We wind up replacing:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  putChunks &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $ compress $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  putChunks &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $ compress $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
      pass [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; ..h-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and modifying the header to indicate we want it to be interlaced.&lt;/p&gt;
&lt;p&gt;This spits out the data in 7 passes refining 8x8 blocks as follows:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1 6 4 6 2 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
3 6 4 6 3 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Done!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 2, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/snippets-mandelbrot/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cellular Automata — Part II: PNGs and Moore</title><link>https://comonad.com/reader/2015/cellular-automata-part-2/</link><guid isPermaLink="false">https://comonad.com/reader/2015/cellular-automata-part-2/</guid><pubDate>Sun, 01 Sep 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 1 September 2013&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/cellular-automata-part-1/&quot;&gt;Last time&lt;/a&gt; I showed how we can render an automaton in your browser using existing tools.&lt;/p&gt;
&lt;p&gt;This time we're going to roll a few of our own, so we can render fancier things. The SVG
we generated last time was just too slow for many users and some folks complained that they couldn't see it at all on an iPad, or that it crashed Firefox.&lt;/p&gt;
&lt;p&gt;To rectify those concerns, we'll start off by writing a PNG generator!&lt;/p&gt;
&lt;h2 id=&quot;folds&quot;&gt;Folds&lt;/h2&gt;
&lt;p&gt;... but I'll take a bit of a circuitous path to get there.&lt;/p&gt;
&lt;p&gt;A couple of weeks back, Gabriel Gonzales posted about his &lt;code&gt;foldl&lt;/code&gt; library. In that he used the following type to capture the essence of a left fold:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; a b = forall x . &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to take a bit of a digression to note a few things about this type, and then show that it is just a presentation of something we already know pretty well in computer science!&lt;/p&gt;
&lt;p&gt;Gabriel proceeded to supply an &lt;code&gt;Applicative&lt;/code&gt; for his &lt;code&gt;Fold&lt;/code&gt; type that looked something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r rb) = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r (f.rb)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; !a !b&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure b = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; (\() _ -&amp;gt; ()) () (\() -&amp;gt; b)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINABLE pure #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; sas s0 s2f &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r0 r2x = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt;
    (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; s r) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (sas s a) (rar r a))
    (&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; s0 r0)
    (\(&lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; s r) -&amp;gt; s2f s (r2x r))
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINABLE (&amp;lt;*&amp;gt;) #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But there is actually a fair bit more we can say about this type!&lt;/p&gt;
&lt;p&gt;Being &lt;code&gt;Applicative&lt;/code&gt;, we can lift numeric operations directly into it:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; b =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = liftA2 (+)
  (-) = liftA2 (-)
  (*) = liftA2 (*)
  abs = fmap abs
  signum = fmap signum
  fromInteger = pure . fromInteger
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; b =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  recip = fmap recip
  (/) = liftA2 (/)
  fromRational = pure . fromRational
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we can also note that it is contravariant in its first argument and covariant in its second, and therefore it &lt;a href=&quot;http://blog.sigfpe.com/2011/07/profunctors-in-haskell.html&quot;&gt;must form&lt;/a&gt; a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/profunctors/3.3.0.1/doc/html/Data-Profunctor.html&quot;&gt;&lt;code&gt;Profunctor&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r0 rb) = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; (\r -&amp;gt; rar r . f) r0 (g . rb)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this does is let us tweak the inputs and/or outputs to our &lt;code&gt;Fold&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what perhaps isn't immediately obvious is that &lt;code&gt;Fold a&lt;/code&gt; forms a &lt;code&gt;Comonad&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; _ r rb) = rb r
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r0 rb) = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r0 $ \r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; rar r rb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the &lt;code&gt;duplicate :: Fold b a -&amp;gt; Fold b (Fold b a)&lt;/code&gt; sneaks in and generates a nested fold &lt;em&gt;before&lt;/em&gt;  the final tweak at the end that destroys our accumulator is applied! It works a bit like a last second pardon from the governor, a stay of execution if you will.&lt;/p&gt;
&lt;h2 id=&quot;a-scary-digression&quot;&gt;A Scary Digression&lt;/h2&gt;
&lt;p&gt;(this is skippable)&lt;/p&gt;
&lt;p&gt;It also forms a somewhat scarier sounding (strong) lax semimonoidal comonad, which just is to say that &lt;code&gt;(&amp;lt;*&amp;gt;)&lt;/code&gt; is well behaved with regards to extract, so we can say:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt;@&amp;gt;) = (&amp;lt;*&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This enables our &lt;code&gt;Comonad&lt;/code&gt; to work with the &lt;code&gt;codo&lt;/code&gt; sugar in Dominic Orchard's &lt;a href=&quot;https://hackage.haskell.org/package/codo-notation&quot;&gt;&lt;code&gt;codo-notation&lt;/code&gt;&lt;/a&gt; package. I won't be doing that today, but you may want to download and modify one of the later examples to use it, just to get a feel for it. It is pretty neat.&lt;/p&gt;
&lt;h2 id=&quot;folding-via-comonad-transformers&quot;&gt;Folding via Comonad Transformers&lt;/h2&gt;
&lt;p&gt;(this part of mostly skippable too)&lt;/p&gt;
&lt;p&gt;I'll get back to the actual usecases for this &lt;code&gt;Comonad&lt;/code&gt; shortly, but first I want to start with ways I could have come up with the definition.&lt;/p&gt;
&lt;p&gt;It turns out there are a few comonads very closely related to Gabriel's left &lt;code&gt;Fold&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;If we take the definition of Gabriel's &lt;code&gt;Fold&lt;/code&gt; and rip off the existential, we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FoldX&lt;/span&gt; x a b = &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we look through the menagerie supplied by the &lt;code&gt;comonad-transformers&lt;/code&gt; package, we can pattern match on that with some effort and find:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FoldX x a b&lt;/code&gt; is isomorphic to both &lt;code&gt;EnvT (x -&amp;gt; a -&amp;gt; x) (Store x) b&lt;/code&gt; and &lt;code&gt;StoreT x (Env (x -&amp;gt; a -&amp;gt; x)) b&lt;/code&gt;. That it matches both of these types isn't surprising.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;Monad&lt;/code&gt; transformers, &lt;code&gt;State&lt;/code&gt;, &lt;code&gt;Reader&lt;/code&gt; and &lt;code&gt;Writer&lt;/code&gt; all commute. In the space of &lt;code&gt;Comonad&lt;/code&gt; transformers, &lt;code&gt;Store&lt;/code&gt;, &lt;code&gt;Env&lt;/code&gt;, and &lt;code&gt;Traced&lt;/code&gt; all commute similarly.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Store&lt;/code&gt; is our old friend from the previous post, but &lt;code&gt;Env&lt;/code&gt; and &lt;code&gt;EnvT&lt;/code&gt; is something we haven't looked at before.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Env&lt;/code&gt; is also pretty much the easiest comonad to derive yourself.&lt;/p&gt;
&lt;p&gt;Give it a shot!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, ScopedTypeVariables #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Exception
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; e a = &lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; e a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- extract :: Env e a -&amp;gt; a&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; e a) = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;unimplemented exercise&quot;&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;-- duplicate :: Env e a -&amp;gt; Env e (Env e a)&lt;/span&gt;
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; e a) = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;unimplemented exercise&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  test &lt;span class=&quot;hljs-string&quot;&gt;&quot;extract&quot;&lt;/span&gt; $ extract (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) == &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  test &lt;span class=&quot;hljs-string&quot;&gt;&quot;duplicate&quot;&lt;/span&gt; $ duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) == &lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; s b = try (return $! b) &amp;gt;&amp;gt;= \ ec -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ec &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (e :: &lt;span class=&quot;hljs-type&quot;&gt;SomeException&lt;/span&gt;) -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; failed: &quot;&lt;/span&gt; ++ show e
  &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; is correct!&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; is not correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we bolt an extra bit of environment onto our &lt;code&gt;Store&lt;/code&gt; from the first part, we get&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;StoreAndEnv&lt;/span&gt; s e a = &lt;span class=&quot;hljs-type&quot;&gt;StoreAndEnv&lt;/span&gt; e (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we fix &lt;code&gt;e = (s -&amp;gt; b -&amp;gt; s)&lt;/code&gt;, we get&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;StoreAndStep&lt;/span&gt; s b a = &lt;span class=&quot;hljs-type&quot;&gt;StoreAndStep&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then if we existentially tie off the &lt;code&gt;s&lt;/code&gt; parameter to keep the end-user from fiddling with it we get back to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; a b = forall s. &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which we could shuffle around into the right place.&lt;/p&gt;
&lt;p&gt;You can view tying off &lt;code&gt;s&lt;/code&gt; as taking a coend if you are so categorically inclined.&lt;/p&gt;
&lt;p&gt;It was somewhat unsatisfying that we had to take a coend and make something existential in that type. Can we do without it?&lt;/p&gt;
&lt;p&gt;It turns out we can, as noted by Elliott Hird, we just need to turn to another &lt;code&gt;Comonad&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&quot;moore-machines&quot;&gt;Moore Machines&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;http://en.wikipedia.org/wiki/Moore_machine&quot;&gt;Moore machine&lt;/a&gt; is one of the two classic ways to represent a &lt;a href=&quot;http://en.wikipedia.org/wiki/Deterministic_finite_automaton&quot;&gt;deterministic finite automaton (DFA)&lt;/a&gt;. The definition we'll use here is going to allow for deterministic infinite automata for free.&lt;/p&gt;
&lt;p&gt;That sort of thing happens a lot in Haskell.&lt;/p&gt;
&lt;p&gt;A Moore machine gives you a result associated with each state in the automaton rather than each edge. We'll make the Moore machine itself represent the state implicitly.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can play around deriving its &lt;code&gt;extract&lt;/code&gt; method below:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor, ScopedTypeVariables #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Exception
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- extract :: Moore b a -&amp;gt; a&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;unimplemented exercise&quot;&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;-- duplicate :: Moore b a -&amp;gt; Moore b (Moore b a)&lt;/span&gt;
  duplicate w@(&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; w (duplicate &amp;lt;$&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)

  &lt;span class=&quot;hljs-comment&quot;&gt;-- extend :: (Moore b a -&amp;gt; c) -&amp;gt; Moore b a -&amp;gt; Moore b c&lt;/span&gt;
  extend f w@(&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)  = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (f w) (extend f &amp;lt;$&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  test &lt;span class=&quot;hljs-string&quot;&gt;&quot;extract&quot;&lt;/span&gt; $ &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; == extract (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; $ error &lt;span class=&quot;hljs-string&quot;&gt;&quot;you don't need to look in the tail&quot;&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; s b = try (return $! b) &amp;gt;&amp;gt;= \ ec -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ec &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (e :: &lt;span class=&quot;hljs-type&quot;&gt;SomeException&lt;/span&gt;) -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; failed: &quot;&lt;/span&gt; ++ show e
  &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; is correct!&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; -&amp;gt; putStrLn $ s ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; is not correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have an eye for this sort of thing, you may have noted that &lt;code&gt;Moore&lt;/code&gt; is a &lt;code&gt;Cofree Comonad&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;That is to say, &lt;code&gt;Moore b a ~ Cofree ((-&amp;gt;) b) a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Moore&lt;/code&gt; machines are supplied in my &lt;code&gt;machines&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;We can also derive an &lt;code&gt;Applicative&lt;/code&gt; for &lt;code&gt;Moore&lt;/code&gt; and all the machinery from the &lt;code&gt;Fold&lt;/code&gt; package, plus our new toys above.&lt;/p&gt;
&lt;p&gt;Here is where I'd love to be able to say that, reformulating things in this simpler way pays off and everything gets faster from using this encoding. Alas, that is not to be.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Moore&lt;/code&gt; machine formulation is about 50% slower than the &lt;code&gt;Fold&lt;/code&gt; representation in part due to the fact that it has hidden information about the environment for our machine from the optimizer. With &lt;code&gt;Fold&lt;/code&gt;, the explicit &lt;code&gt;s&lt;/code&gt; can be manipulated by the inliner very easily.&lt;/p&gt;
&lt;p&gt;Moreover applying an &lt;code&gt;fmap&lt;/code&gt; is clearly done at the end, and so you pay no real cost for it until after the last iteration of the loop.&lt;/p&gt;
&lt;p&gt;However, with the &lt;code&gt;Moore&lt;/code&gt; representation, we pay for each &lt;code&gt;fmap&lt;/code&gt;, because it winds up entangled in our core loop forever and we have to 'step over it' to get to the actual core of work we want to do. If we apply the co-&lt;code&gt;Yoneda&lt;/code&gt; lemma to our Moore machine, we get&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;YonedaMoore&lt;/span&gt; a b = forall r. &lt;span class=&quot;hljs-type&quot;&gt;YonedaMoore&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you get rid of the overhead for each &lt;code&gt;fmap&lt;/code&gt;, but we've brought back the existential and just made the optimizer's job harder.&lt;/p&gt;
&lt;p&gt;What we do gain is flexibility in exchange for a bit of speed and no need for extensions.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;Moore&lt;/code&gt; machine can represent a mixture of strict and lazy left folds without extra boxes. The &lt;code&gt;Fold&lt;/code&gt; type we started with can only represent one or the other easily, but otherwise must use a box around the intermediate value type. The choice is made when you go to apply the &lt;code&gt;Fold&lt;/code&gt;. Gabriel has chosen (rightly) to focus on strict left folds.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;Moore&lt;/code&gt; we can define the embedding to either be lazy&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;moorel&lt;/span&gt; :: (a -&amp;gt; b -&amp;gt; a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a
&lt;span class=&quot;hljs-title&quot;&gt;moorel&lt;/span&gt; f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (go . f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or strict&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;moorel'&lt;/span&gt; :: (a -&amp;gt; b -&amp;gt; a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a
&lt;span class=&quot;hljs-title&quot;&gt;moorel'&lt;/span&gt; f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go !a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (go . f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and because we don't have an explicit 's' parameter, we don't have to put a &lt;code&gt;Box&lt;/code&gt; around it if we want the lazy version.&lt;/p&gt;
&lt;p&gt;Then the kinds of combinators supplied by &lt;code&gt;Fold&lt;/code&gt; can be implemented as&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;total&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a a
&lt;span class=&quot;hljs-title&quot;&gt;total&lt;/span&gt; = moorel' (+) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;count&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a
&lt;span class=&quot;hljs-title&quot;&gt;count&lt;/span&gt; = moorel' (\a _ -&amp;gt; a + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Fold&lt;/code&gt; and &lt;code&gt;Moore&lt;/code&gt; are equivalent in expressive power, so another way to think about a &lt;code&gt;Fold&lt;/code&gt; is as &lt;code&gt;Cofree ((-&amp;gt;) a)&lt;/code&gt; represented with an explicit seed in the style of &lt;code&gt;Nu&lt;/code&gt; from my &lt;a href=&quot;https://hackage.haskell.org/package/recursion-schemes&quot;&gt;&lt;code&gt;recursion-schemes&lt;/code&gt;&lt;/a&gt; package!&lt;/p&gt;
&lt;h2 id=&quot;feeding-machines-and-folds&quot;&gt;Feeding Machines and Folds&lt;/h2&gt;
&lt;p&gt;If we redefine our &lt;code&gt;Moore&lt;/code&gt; machine using record syntax:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;this&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;less&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then we can run one of our &lt;code&gt;Moore&lt;/code&gt; machines by continually calling &lt;code&gt;less&lt;/code&gt; with new inputs and then extracting the answer for its final result state.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; t =&amp;gt; t b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; xs m = extract (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;.foldl' less m xs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that even though I'm using foldl' here, the thing that is being strictly updated is the Moore machine, not its member, which is only strict if you &lt;em&gt;built&lt;/em&gt; the Moore machine using &lt;code&gt;moorel'&lt;/code&gt; above.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;more xs&lt;/code&gt; is now a &lt;code&gt;Cokleisli&lt;/code&gt; arrow for our &lt;code&gt;Comonad&lt;/code&gt;, just like &lt;code&gt;rule 110&lt;/code&gt; was for our &lt;code&gt;Store&lt;/code&gt; &lt;code&gt;Comonad&lt;/code&gt; in the last post.&lt;/p&gt;
&lt;p&gt;We can construct a similar version of &lt;code&gt;more&lt;/code&gt; for &lt;code&gt;Fold&lt;/code&gt; using Gabriel's &lt;code&gt;fold&lt;/code&gt; combinator.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; t =&amp;gt; t b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; b a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; xs m = extract (fold m xs)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-does-the-comonad-for-fold-mean&quot;&gt;What does the Comonad for Fold mean?&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;Comonad&lt;/code&gt; for &lt;code&gt;Fold a&lt;/code&gt; or &lt;code&gt;Moore&lt;/code&gt; enables us to partially apply a &lt;code&gt;Fold&lt;/code&gt; or &lt;code&gt;Moore&lt;/code&gt; machine to some input and then resume it later.&lt;/p&gt;
&lt;p&gt;If we &lt;code&gt;extend (more xs)&lt;/code&gt; we get the ability to resume it with additional input, having partially driven our &lt;code&gt;Fold&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;If we turn to &lt;code&gt;(=&amp;lt;=)&lt;/code&gt; from &lt;code&gt;Control.Comonad&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(=&amp;lt;=) :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (w b -&amp;gt; c) -&amp;gt; (w a -&amp;gt; b) -&amp;gt; w a -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; =&amp;lt;= g = f . extend g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can express the laws for &lt;code&gt;more&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extract&lt;/span&gt; = more []
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; =&amp;lt;= more bs = more (&lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ++ bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;more&lt;/code&gt; provides us a monoid homomorphism between Cokleisli composition and concatenation.&lt;/p&gt;
&lt;p&gt;Operationally, it sneaks in before you apply the last step to convert from your intermediate accumulator to the final result and lets you continue to do more work on the accumulator.&lt;/p&gt;
&lt;p&gt;This strikes me as not intuitively obvious, because unless you look at it carefully, it isn't immediately obvious that you can resume something like a hash function because at the end, you usually tweak the result before giving it to the user. Here because we have access to the internals of the Comonad, we can &lt;code&gt;duplicate&lt;/code&gt; them into the result before closing it off.&lt;/p&gt;
&lt;p&gt;This is where the explicit seed pays off, because that &lt;code&gt;duplicate&lt;/code&gt; incurs no overhead during the actual traversal under Gabriel's representation.&lt;/p&gt;
&lt;p&gt;This same existential construction works for &lt;code&gt;foldMap&lt;/code&gt;- and &lt;code&gt;foldr&lt;/code&gt;-based folds as well, though most of the &quot;stream fusion&quot; benefits require you to be able to stream and so &lt;code&gt;foldMap&lt;/code&gt;-like structures, sadly, get little benefit.&lt;/p&gt;
&lt;h2 id=&quot;resuming-a-hash-function&quot;&gt;Resuming a Hash Function&lt;/h2&gt;
&lt;p&gt;Let us consider a couple of CRC-like functions, to have something non-trivial to fold.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;adler32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;adler32&lt;/span&gt; = done &amp;lt;$&amp;gt; moorel' step (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1 s2) x = &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1' s2' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    s1' = mod (s1 + fromIntegral x) &lt;span class=&quot;hljs-number&quot;&gt;65521&lt;/span&gt;
    s2' = mod (s1' + s2) &lt;span class=&quot;hljs-number&quot;&gt;65521&lt;/span&gt;
  done (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1 s2) = unsafeShiftL s2 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; + s1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;a href=&quot;http://en.wikipedia.org/wiki/Adler-32&quot;&gt;Adler32&lt;/a&gt;, the final step of hashing destroys the separation of information between &lt;code&gt;s1&lt;/code&gt; and &lt;code&gt;s2&lt;/code&gt;, but we can sneak in with the comonad before we destroy it and resume!&lt;/p&gt;
&lt;p&gt;Similarly, but less catastrophically, in &lt;a href=&quot;http://en.wikipedia.org/wiki/Cyclic_redundancy_check&quot;&gt;CRC32&lt;/a&gt; the final step is to complement the input.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = complement &amp;lt;$&amp;gt; moorel' step &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; `xor` (crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;))

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can describe similar &lt;code&gt;Moore&lt;/code&gt; machines (or &lt;code&gt;Fold&lt;/code&gt;s) for common hashing functions, and then we don't need to make up separate functions for initializing the state, feeding them some incremental additional data and finally cleaning up when we're done.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Moore&lt;/code&gt; machine provides you with all of that, and the entire API necessary to interact with them comes down to feeding it &lt;code&gt;more&lt;/code&gt;, extending after doing so to accept more input!&lt;/p&gt;
&lt;p&gt;This strikes me as an incredibly clean implementation pattern for HMACs such as &lt;a href=&quot;http://en.wikipedia.org/wiki/MD5&quot;&gt;MD5&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-1&quot;&gt;SHA&lt;/a&gt; in Haskell. You don't need to name 3 separate pieces.&lt;/p&gt;
&lt;p&gt;You just name the HMAC itself as the Moore machine that produces it. Then you can feed it &lt;code&gt;more&lt;/code&gt; data, extending it as needed until you finally go to look at the last result.&lt;/p&gt;
&lt;h2 id=&quot;uncompressed-pngs&quot;&gt;Uncompressed PNGs&lt;/h2&gt;
&lt;p&gt;So let's put our code where our mouth is and show that we can use this to do some software engineering by writing some code to produce a &lt;a href=&quot;http://en.wikipedia.org/wiki/Portable_Network_Graphics&quot;&gt;PNG&lt;/a&gt; image from scratch in Haskell.&lt;/p&gt;
&lt;p&gt;A bit over a year ago, Keegan McAllister wrote a nice &lt;a href=&quot;http://mainisusuallyafunction.blogspot.com/2012/04/minimal-encoder-for-uncompressed-pngs.html&quot;&gt;post&lt;/a&gt; on how to generate a minimal uncompressed PNG using python. We'll copy his development here, except we'll switch out to the nicer table-based crc32 above.&lt;/p&gt;
&lt;p&gt;As he noted, you need to implement two hash functions to actually get through writing an uncompressed PNG. Hrmm. We appear to have those.&lt;/p&gt;
&lt;p&gt;We'll use &lt;code&gt;Data.Binary&lt;/code&gt; to write out the results, mostly because PNG is an annoyingly introspective format, so we'll have to talk about the lengths of fragments we're generating as we go.&lt;/p&gt;
&lt;p&gt;We can write the ability to put a PNG 'chunk' out, which consists of a 4 byte header followed by some data, but which first encodes the length of just the data, then emits the header, then the data, and finally closes off the chunk with the CRC32 of both.&lt;/p&gt;
&lt;p&gt;Let's generalize more to work over any &lt;code&gt;Fold&lt;/code&gt; (in the &lt;code&gt;lens&lt;/code&gt; sense this time!) that yields the input type.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;moreOf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a))) s b -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;moreOf&lt;/span&gt; l xs m = extract (foldlOf' l less m xs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That somewhat baroque seeming type can be read as a more liberal version of:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;moreOf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Fold&lt;/span&gt; s b -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;that just happens to get better inference due to the lack of rank-2 types.&lt;/p&gt;
&lt;p&gt;Now we can use it directly on the lazy bytestring fragments we get along the way&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; h (runPut -&amp;gt; b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b)
  putLazyByteString h
  putLazyByteString b
  putWord32be $ moreOf bytes h =&amp;lt;= moreOf bytes b $ crc32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To write out a PNG file, we need to be able to emit the &lt;code&gt;IHDR&lt;/code&gt; chunk, 1 or more &lt;code&gt;IDAT&lt;/code&gt; chunks of zlib compressed data, and an &lt;code&gt;IEND&lt;/code&gt; chunk.&lt;/p&gt;
&lt;p&gt;We can break up our zlib data into uncompressed blocks. However, zlib only allows uncompressed runs of 64k at a time, so we let's define the encoding for a nested uncompressed deflate block.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;deflated&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;deflated&lt;/span&gt; final b | l &amp;lt;- fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord8 $ &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; final &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putWord16le l &lt;span class=&quot;hljs-comment&quot;&gt;-- yep, now it's little endian!&lt;/span&gt;
  putWord16le (complement l)
  putLazyByteString b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we just rip our input up into 64k blocks, embed each of those blocks in one enormous &lt;code&gt;IDAT&lt;/code&gt; block, then finally seal everything up with the &lt;code&gt;Adler32&lt;/code&gt; checksum that we so helpfully supplied as an example above!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;zlibbed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;zlibbed&lt;/span&gt; bs = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0x78&lt;/span&gt;
  putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0x01&lt;/span&gt;
  go bs
  putWord32be $ moreOf bytes bs adler32
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.splitAt &lt;span class=&quot;hljs-number&quot;&gt;0xffff&lt;/span&gt; -&amp;gt; (xs, ys)) | done &amp;lt;- &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.null ys = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      deflated done xs
      &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt;.unless done (go ys)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can write out a PNG header, loop through the data, state that we're not applying any transformation for each row:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; w fs = runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putLazyByteString &lt;span class=&quot;hljs-string&quot;&gt;&quot;\x89PNG\r\n\x1a\n&quot;&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IHDR&quot;&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    putWord32be $ fromIntegral w
    putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt;.length fs)
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 8 bit color depth&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- RGB&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $ zlibbed (runPut rows)
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IEND&quot;&lt;/span&gt; $ return ()
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    rows = forM_ fs $ \f -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      forM_ [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] (put . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here I've chosen to tell the PNG the width, but leave height implicit in the length of the list of functions from horizontal position to pixel color. I may revisit that later, but it was the fastest thing I could think of to write.&lt;/p&gt;
&lt;p&gt;This lets &lt;code&gt;png&lt;/code&gt; nicely fit into the recursion pattern from the previous post.&lt;/p&gt;
&lt;p&gt;But we've written a lot of code, so it'd be nice to check that we generated a valid PNG.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE BangPatterns #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ViewPatterns #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# OPTIONS_GHC -Wall #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Control.Monad &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; M
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary.Put
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.ByteString.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; F
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; List
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Moore machines&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;this&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;less&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) = liftA2 (+)
  (-) = liftA2 (-)
  (*) = liftA2 (*)
  abs = fmap abs
  signum = fmap signum
  fromInteger = pure . fromInteger
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  recip = fmap recip
  (/) = liftA2 (/)
  fromRational = pure . fromRational
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; go (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a k) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (f a) (go . k)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract = this
  duplicate w@(&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; w (duplicate . &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadApply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (&amp;lt;@&amp;gt;) = (&amp;lt;*&amp;gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (const &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
  &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; f fs &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (f a) $ \b -&amp;gt; fs b &amp;lt;*&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Profunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  dimap f g (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; (g a) (dimap f g . &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; . f)

&lt;span class=&quot;hljs-title&quot;&gt;moorel&lt;/span&gt; :: (a -&amp;gt; b -&amp;gt; a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a
&lt;span class=&quot;hljs-title&quot;&gt;moorel&lt;/span&gt; f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; go a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (go . f a)

&lt;span class=&quot;hljs-title&quot;&gt;moorel'&lt;/span&gt; :: (a -&amp;gt; b -&amp;gt; a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a
&lt;span class=&quot;hljs-title&quot;&gt;moorel'&lt;/span&gt; f = go &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; go !a = &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; a (go . f a)

&lt;span class=&quot;hljs-title&quot;&gt;moreOf&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a))) s b -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; b a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;moreOf&lt;/span&gt; l xs m = extract (foldlOf' l less m xs)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Adler 32&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;adler32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;adler32&lt;/span&gt; = done &amp;lt;$&amp;gt; moorel' step (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1 s2) x = &lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1' s2' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    s1' = mod (s1 + fromIntegral x) &lt;span class=&quot;hljs-number&quot;&gt;65521&lt;/span&gt;
    s2' = mod (s1' + s2) &lt;span class=&quot;hljs-number&quot;&gt;65521&lt;/span&gt;
  done (&lt;span class=&quot;hljs-type&quot;&gt;Adler32&lt;/span&gt; s1 s2) = unsafeShiftL s2 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; + s1

&lt;span class=&quot;hljs-comment&quot;&gt;-- * CRC32&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Moore&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = complement &amp;lt;$&amp;gt; moorel' step &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; `xor` crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- * PNG&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; h (runPut -&amp;gt; b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b)
  putLazyByteString h
  putLazyByteString b
  putWord32be $ moreOf bytes h =&amp;lt;= moreOf bytes b $ crc32

&lt;span class=&quot;hljs-title&quot;&gt;deflated&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;deflated&lt;/span&gt; final b | l &amp;lt;- fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord8 $ &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; final &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putWord16le l &lt;span class=&quot;hljs-comment&quot;&gt;-- yep, now it's little endian!&lt;/span&gt;
  putWord16le (complement l)
  putLazyByteString b

&lt;span class=&quot;hljs-title&quot;&gt;zlibbed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;zlibbed&lt;/span&gt; bs = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0x78&lt;/span&gt;
  putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0x01&lt;/span&gt;
  go bs
  putWord32be $ moreOf bytes bs adler32
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.splitAt &lt;span class=&quot;hljs-number&quot;&gt;0xffff&lt;/span&gt; -&amp;gt; (xs, ys)) | done &amp;lt;- &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.null ys = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      deflated done xs
      &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt;.unless done (go ys)

&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; w fs = runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putLazyByteString &lt;span class=&quot;hljs-string&quot;&gt;&quot;\x89PNG\r\n\x1a\n&quot;&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IHDR&quot;&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    putWord32be $ fromIntegral w
    putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt;.length fs)
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 8 bit color depth&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- RGB&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $ zlibbed (runPut rows)
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IEND&quot;&lt;/span&gt; $ return ()
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    rows = forM_ fs $ \f -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      forM_ [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] (put . f)

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Yesod&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yesod&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;

mkYesod &quot;&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&quot; [parseRoutes| / &lt;span class=&quot;hljs-type&quot;&gt;ImageR&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GET&lt;/span&gt; |]

main :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
main = warpEnv &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;


getImageR :: &lt;span class=&quot;hljs-type&quot;&gt;MonadHandler&lt;/span&gt; m =&amp;gt; m &lt;span class=&quot;hljs-type&quot;&gt;TypedContent&lt;/span&gt;
getImageR = sendResponse $ toTypedContent (&lt;span class=&quot;hljs-title&quot;&gt;typePng&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;toContent&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;img&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  img = png &lt;span class=&quot;hljs-number&quot;&gt;500&lt;/span&gt; $ take &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt; $ pixel &amp;lt;$&amp;gt; [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..]
  pixel y x = (fromIntegral x,fromInteger y,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That image matches up byte for byte with the output of Keegan's sample, so we seem to have an end-to-end test that works.&lt;/p&gt;
&lt;p&gt;A lot of this code is redundant, however.&lt;/p&gt;
&lt;p&gt;For instance all of the &lt;code&gt;Moore&lt;/code&gt; code could be taken from the &lt;code&gt;machines&lt;/code&gt; package, which provides &lt;code&gt;Data.Machine.Moore&lt;/code&gt; along with all of these instances! Then with a bit of tightening of exposition and removing unnecessary detours we could generate the whole thing in a lot less code.&lt;/p&gt;
&lt;h2 id=&quot;automata-please&quot;&gt;Automata, Please&lt;/h2&gt;
&lt;p&gt;Of course, this is supposed to be a series about cellular automata. So let's draw one.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/#png-automaton-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;1.) I'll be switching to a 4 line minimalist version of Gabriel's &lt;code&gt;foldl&lt;/code&gt; library, rather than using the &lt;code&gt;Moore&lt;/code&gt; representation, since we don't need any of the instances. I've renamed his &lt;code&gt;Fold&lt;/code&gt; to &lt;code&gt;L&lt;/code&gt; here to avoid conflicts with the &lt;code&gt;Lens&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;2.) We don't &lt;em&gt;need&lt;/em&gt; to use the &lt;code&gt;Comonad&lt;/code&gt; for the fold type we spent all that time above building up. Here we're working with lazy bytestrings, so let's just append them in the one case we need!&lt;/p&gt;
&lt;p&gt;2.) I'll also be using the &lt;code&gt;Context&lt;/code&gt; comonad from the &lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt; package rather than continuing to roll our own &lt;code&gt;Store&lt;/code&gt;. That'll be useful next time when I want to abuse the separate indices.&lt;/p&gt;
&lt;p&gt;3.)
I've tweaked the memoization rule to use&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (tab . extend f) . tab
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;instead of&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (extend f . tab)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to get slightly better memoization. I also switched to &lt;code&gt;representable-tries&lt;/code&gt;,
because it'll make it easier to switch to new topologies later.&lt;/p&gt;
&lt;p&gt;4.) Finally, to reduce the footprint of the PNGs we generate we'll let the existing &lt;code&gt;zlib&lt;/code&gt; bindings for Haskell do the compression rather than manually deflate. This reduces the footprint of the generated images a great deal.&lt;/p&gt;
&lt;p&gt;Click Run!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ExistentialQuantification #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE Rank2Types #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Codec.Compression.Zlib
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens.Internal.Context
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Binary.Put
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; F
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.MemoTrie
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; f s) = testBit w $ &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits .~ [f (s+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), f s, f (s-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]

&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HasTrie&lt;/span&gt; s =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; s s a]
&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (tab . extend f) . tab &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  tab (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; k s) = &lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (memo k) s

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; b a = forall x. &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;more&lt;/span&gt; bs (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; xbx x xa) = xa (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.foldl' xbx x bs)

&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crc32&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; step &lt;span class=&quot;hljs-number&quot;&gt;0xffffffff&lt;/span&gt; complement &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step r b = unsafeShiftR r &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; `xor` crcs &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.! fromIntegral (xor r (fromIntegral b) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xff&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;crcs&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.generate &lt;span class=&quot;hljs-number&quot;&gt;256&lt;/span&gt; (go.go.go.go.go.go.go.go.fromIntegral) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go c = unsafeShiftR c &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; `xor` &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; c .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; /= &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xedb88320&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Put&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;putChunk&lt;/span&gt; h b = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putWord32be $ fromIntegral (&lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.length b)
  putLazyByteString h
  putLazyByteString b
  putWord32be $ more (h &amp;lt;&amp;gt; b) crc32

&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt;)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;png&lt;/span&gt; w h fs = runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  putLazyByteString &lt;span class=&quot;hljs-string&quot;&gt;&quot;\x89PNG\r\n\x1a\n&quot;&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IHDR&quot;&lt;/span&gt; $ runPut $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    putWord32be (fromIntegral w)
    putWord32be (fromIntegral h)
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 8 bit color depth&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- RGB&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IDAT&quot;&lt;/span&gt; $
    compressWith defaultCompressParams { compressLevel = bestSpeed } $
    runPut $ forM_ (take h fs) $ \f -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
      putWord8 &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
      forM_ [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;..w-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] (put . f)
  putChunk &lt;span class=&quot;hljs-string&quot;&gt;&quot;IEND&quot;&lt;/span&gt; mempty

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yesod&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;
mkYesod &quot;&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&quot; [parseRoutes| / &lt;span class=&quot;hljs-type&quot;&gt;ImageR&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GET&lt;/span&gt; |]
main = warpEnv &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;


getImageR :: &lt;span class=&quot;hljs-type&quot;&gt;MonadHandler&lt;/span&gt; m =&amp;gt; m &lt;span class=&quot;hljs-type&quot;&gt;TypedContent&lt;/span&gt;
getImageR = sendResponse $ toTypedContent (&lt;span class=&quot;hljs-title&quot;&gt;typePng&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;toContent&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;img&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  img = png &lt;span class=&quot;hljs-number&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;150&lt;/span&gt; $ draw &amp;lt;$&amp;gt; loop (rule &lt;span class=&quot;hljs-number&quot;&gt;110&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; (==&lt;span class=&quot;hljs-number&quot;&gt;149&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;149&lt;/span&gt;)
  draw (&lt;span class=&quot;hljs-type&quot;&gt;Context&lt;/span&gt; p _) x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; p x &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; (&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;255&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That weighs in somewhere around 75 lines, and includes our compressed PNG generator, all the logic for running Wolfram's 2-color rules as before, and our embedded Yesod server. You can feel free to tweak the output above.&lt;/p&gt;
&lt;p&gt;In the real world you'd probably just use &lt;a href=&quot;https://hackage.haskell.org/packages/archive/JuicyPixels/3.1/doc/html/Codec-Picture-Png.html&quot;&gt;JuicyPixels&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now that we're not shackled by the SVG rendering speed we can generalize this to other topologies and maybe try to improve on our other bottlenecks in future updates.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;September 1, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2015/cellular-automata-part-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Episode 1 — On Lenses</title><link>https://comonad.com/reader/talks/kmett-2013-haskellcast-lenses/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2013-haskellcast-lenses/</guid><pubDate>Mon, 26 Aug 2013 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 26 August 2013 · published&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;6GNDzrgFhGM&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6GNDzrgFhGM&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Episode 1 — Edward Kmett on Lenses — The Haskell Cast.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.haskellcast.com/episode/001-edward-kmett-on-lenses&quot;&gt;mp3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.haskellcast.com/episode/001-edward-kmett-on-lenses&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6GNDzrgFhGM&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2013-haskellcast-lenses/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part VI: A Most Significant Comparison</title><link>https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-6/</link><guid isPermaLink="false">https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-6/</guid><pubDate>Sun, 25 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 August 2013&lt;/p&gt;&lt;p&gt;I was going to finally get to the point, but I decided it would be good to consolidate our understanding of &quot;the most significant difference&quot; from the &lt;a href=&quot;https://comonad.com/reader/series/revisiting-matrix-multiplication/&quot;&gt;previous parts&lt;/a&gt; into a single short summary.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://en.wikipedia.org/wiki/Punxsutawney_Phil&quot;&gt;groundhog&lt;/a&gt; has seen his shadow and you are in for six more weeks of winter.&lt;/p&gt;
&lt;h2 id=&quot;morton-order-redux&quot;&gt;Morton Order Redux&lt;/h2&gt;
&lt;p&gt;Recall our rather boring definition of a Morton-ordered &lt;code&gt;Key&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to refactor the trick for comparing in &lt;a href=&quot;http://en.wikipedia.org/wiki/Z-order_curve&quot;&gt;Morton order&lt;/a&gt; from &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;Part 2&lt;/a&gt; that we revisited in &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/&quot;&gt;Part 4&lt;/a&gt; into a more reusable form.&lt;/p&gt;
&lt;p&gt;To that end, let us consider how to compare two unsigned words for how they differ in the placement of their most significant bit.&lt;/p&gt;
&lt;p&gt;Logically I want to &lt;code&gt;on compare msb&lt;/code&gt;, without paying for calculating the position of the most significant bit directly.&lt;/p&gt;
&lt;p&gt;To do I first observe that we can first compare our two values &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If they match, then trivially they agree on the position of their most significant set bit!&lt;/p&gt;
&lt;p&gt;If they don't, then either &lt;code&gt;a &amp;lt; b&lt;/code&gt; or &lt;code&gt;b &amp;lt; a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Without loss of generality, let's assume &lt;code&gt;a &amp;lt; b&lt;/code&gt;. Then either &lt;code&gt;a&lt;/code&gt; had the same &lt;code&gt;msb&lt;/code&gt; as &lt;code&gt;b&lt;/code&gt; or it doesn't.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;a&lt;/code&gt; had the same &lt;code&gt;msb&lt;/code&gt; as &lt;code&gt;b&lt;/code&gt; then &lt;code&gt;xor a b&lt;/code&gt; will not have that bit set, so &lt;code&gt;a &amp;lt; xor a b&lt;/code&gt; will be &lt;code&gt;False&lt;/code&gt; as &lt;code&gt;a&lt;/code&gt; as a more significant bit set than &lt;code&gt;xor a b&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;a&lt;/code&gt; does not have the same &lt;code&gt;msb&lt;/code&gt; as &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;a &amp;lt; b&lt;/code&gt;, then &lt;code&gt;b&lt;/code&gt; has it set, and &lt;code&gt;a&lt;/code&gt; does not, so the more significant bit will be set in &lt;code&gt;xor a b&lt;/code&gt;, and &lt;code&gt;a &amp;lt; xor a b&lt;/code&gt; will be &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Putting all of this logic together yields the following combinator:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word


&lt;span class=&quot;hljs-title&quot;&gt;compares&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;compares&lt;/span&gt; a b = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; | a &amp;lt; xor a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; | b &amp;lt; xor a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt;
  _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ compares &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can similarly reason through specialized scenaros to obtain &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;/=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt; restricted to the most significant bit.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word


&lt;span class=&quot;hljs-title&quot;&gt;lts&lt;/span&gt;, les, eqs, nes, ges, gts :: &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lts&lt;/span&gt; a b = a &amp;lt; b &amp;amp;&amp;amp; a &amp;lt; xor a b
&lt;span class=&quot;hljs-title&quot;&gt;les&lt;/span&gt; a b = a &amp;lt;= b || xor a b &amp;lt;= b

&lt;span class=&quot;hljs-title&quot;&gt;eqs&lt;/span&gt; a b = a &amp;gt;= min b c &amp;amp;&amp;amp; b &amp;gt;= max a c &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; c = xor a b
&lt;span class=&quot;hljs-title&quot;&gt;nes&lt;/span&gt; a b = a &amp;lt;  min b c || b &amp;lt;  min a c &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; c = xor a b
&lt;span class=&quot;hljs-comment&quot;&gt;-- show ...&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;gts&lt;/span&gt; a b = a &amp;gt; b &amp;amp;&amp;amp; xor a b &amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;ges&lt;/span&gt; a b = a &amp;gt;= b || a &amp;gt;= xor a b

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ les &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can see our earlier &lt;code&gt;Ord&lt;/code&gt; instance for &lt;code&gt;Key&lt;/code&gt; is just:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;lts&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lts&lt;/span&gt; a b = a &amp;lt; b &amp;amp;&amp;amp; a &amp;lt; xor a b
&lt;span class=&quot;hljs-class&quot;&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b `compare` &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; c d
    | xor a c `lts` xor b d = compare b d
    | otherwise             = compare a c

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that is much easier to read:&lt;/p&gt;
&lt;p&gt;If the most significant difference betwen &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; is less significant than the most significant difference between &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt;, then we should just compare &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt;, otherwise we compare &lt;code&gt;a&lt;/code&gt; with &lt;code&gt;c&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;one-of-these-things-is-not-like-the-others&quot;&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=FClGhto1vIg&amp;t=11s&quot;&gt;One of these things is not like the others&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This makes it clear why we had three uses of &lt;code&gt;xor&lt;/code&gt; in the original, the first two were to calculate the differences themselves, while the last &lt;code&gt;xor&lt;/code&gt; was simply to compare by most significant bit!&lt;/p&gt;
&lt;p&gt;Switching to these internally made almost a factor of two difference in the performance of the overall multiplier relative to actually performing the masking! This bodes well for the practicality of the as-yet-still-unbenchmarked &lt;code&gt;IntMap&lt;/code&gt; alternative described in &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/&quot;&gt;part 4&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 25 2013&lt;/p&gt;
&lt;p&gt;P.S. This also means I effectively just claimed No-Prize #5 for myself. ;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-6/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part IV: IntMap!?</title><link>https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/</link><guid isPermaLink="false">https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/</guid><pubDate>Sun, 25 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 August 2013&lt;/p&gt;&lt;p&gt;Back in &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;part 2&lt;/a&gt; we showed how we can compare two keys in Morton order without having to actually do the interleaving.&lt;/p&gt;
&lt;p&gt;I'm going to take some time today to try to help folks build intuition for what that means by taking a look at an old standby in the Haskell ecosystem, &lt;code&gt;Data.IntMap&lt;/code&gt;, and use the techniques we developed in part 2 to generate a version of some of the core routines that uses the same &lt;code&gt;xor&lt;/code&gt; trick rather than store the prefix and mask it stores today.&lt;/p&gt;
&lt;p&gt;Nothing in here has to do with matrix multiplication, but it is a powerful application of the notion of a &quot;most significant difference&quot; and &lt;code&gt;xor&lt;/code&gt; based comparison by it.&lt;/p&gt;
&lt;p&gt;If you're just getting here, you might want to start with parts &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;2&lt;/a&gt; and &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/&quot;&gt;3&lt;/a&gt;, but there is no pressure. Like &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/&quot;&gt;part 3&lt;/a&gt;, this post can largely stand alone.&lt;/p&gt;
&lt;h2 id=&quot;intmap&quot;&gt;IntMap?!&lt;/h2&gt;
&lt;p&gt;Changing to my &quot;difference tree&quot; approach permits a number of operations to terminate earlier, and may well turn out to be a viable way to improve the venerable &lt;code&gt;IntMap&lt;/code&gt; in the &lt;code&gt;containers&lt;/code&gt; package, but I'm using it here mostly to help us develop familiarity with the 'most significant most significant difference'.&lt;/p&gt;
&lt;p&gt;In many ways this is a degenerate case, but it at least helps us develop some facility for using the tool!&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;Data.IntMap.Base&lt;/code&gt;, based on some decade old code from &lt;a href=&quot;http://research.microsoft.com/en-us/people/daan/&quot;&gt;Daan Leijen&lt;/a&gt;, the &lt;code&gt;containers&lt;/code&gt; library defines:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Prefix&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mask&lt;/span&gt;   = &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Prefix&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Mask&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Prefix&lt;/code&gt; and &lt;code&gt;Mask&lt;/code&gt; contain information about the known common prefix of the PATRICIA trie up to that point, and the &lt;code&gt;Mask&lt;/code&gt; of the position where they diverge.&lt;/p&gt;
&lt;p&gt;Using what we now know, we can change this to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the values we store in the &lt;code&gt;Bin&lt;/code&gt; constructor are just the minimum and maximum &lt;code&gt;Int&lt;/code&gt; key in the tree below.&lt;/p&gt;
&lt;h2 id=&quot;classifying-keys&quot;&gt;Classifying Keys&lt;/h2&gt;
&lt;p&gt;To do so we need to be able to distinguish between roughly 6 cases for how a key can interact with the map, as if we had the &lt;code&gt;Prefix&lt;/code&gt; and &lt;code&gt;Mask&lt;/code&gt; in hand. From left to right:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;FarLeft&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearLeft&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InLeft&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;-- within the left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InRight&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- within the right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearRight&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;FarRight&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside right branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;xor&lt;/code&gt; trick I mentioned at the end of part 2 can be bundled into a slightly unwieldy combinator, &lt;code&gt;significant&lt;/code&gt; such that &lt;code&gt;significant a b c d&lt;/code&gt; implies that the position of the most significant difference between &lt;code&gt;c&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt; dominates the position of the most significant difference between &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; a b c d = ab &amp;lt; cd &amp;amp;&amp;amp; ab &amp;lt; xor ab cd &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  cd = xor c d
  ab = xor a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can proceed to use trickery and slight of hand to classify our keys with regards to the bounds of our &lt;code&gt;IntMap&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;FarLeft&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearLeft&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InLeft&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;-- within the left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InRight&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- within the right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearRight&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;FarRight&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside right branch&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; a b c d = ab &amp;lt; cd &amp;amp;&amp;amp; ab &amp;lt; xor ab cd &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  cd = xor c d
  ab = xor a b


&lt;span class=&quot;hljs-title&quot;&gt;classify&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;classify&lt;/span&gt; k x y
  | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FarLeft&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NearLeft&lt;/span&gt;
  | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FarRight&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NearRight&lt;/span&gt;
  | significant k y x y = &lt;span class=&quot;hljs-type&quot;&gt;InRight&lt;/span&gt;
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;InLeft&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ classify &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We don't need to use the full power of classify, as often some subset of those 6 cases will be the same, so lets define a couple of additional combinators:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;outside&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;outside&lt;/span&gt; k x y = k &amp;lt; x || k &amp;gt; y

&lt;span class=&quot;hljs-title&quot;&gt;insideR&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;insideR&lt;/span&gt; k x y = significant k y x y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;outside&lt;/code&gt; serves as a more accurate version of &lt;code&gt;nomatch&lt;/code&gt; from the &lt;code&gt;Data.IntMap&lt;/code&gt; internals, and &lt;code&gt;insideR&lt;/code&gt; assumes we're inside the range &lt;code&gt;[x..y]&lt;/code&gt; and notes that if there is an extra bit of difference between &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; than between &lt;code&gt;k&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, then we're in the right branch.&lt;/p&gt;
&lt;p&gt;We simply use integer comparisons and 3 &lt;code&gt;xor&lt;/code&gt;s to classify how our key relates to the range of our &lt;code&gt;IntMap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We won't actually be using &lt;code&gt;classify&lt;/code&gt; explicitly but you can play with it to see if you agree with its results! You'll be able to see it conceptually at work in the code below though.&lt;/p&gt;
&lt;h2 id=&quot;stock-definitions&quot;&gt;Stock Definitions&lt;/h2&gt;
&lt;p&gt;Some of the stock combinators don't change at all:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; _   = &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly the instances don't change:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y &amp;lt;$&amp;gt; go l &amp;lt;*&amp;gt; go r
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x &amp;lt;$&amp;gt; f a
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = pure &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE traverse #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = mempty
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; _ a) = f a
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ _ l r) = mappend (go l) (go r)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE foldMap #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x (f a)
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y (go l) (go r)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE fmap #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but fast new friends become possible.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;           = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; i a)     = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (i,i)
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; i j _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (i,j)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given the common usecase of finding the maximum key in an &lt;code&gt;IntMap&lt;/code&gt; and inserting a new entry, that is a pretty nice side-effect!&lt;/p&gt;
&lt;h2 id=&quot;lookup&quot;&gt;Lookup&lt;/h2&gt;
&lt;p&gt;The next combinator to benefit from this change is &lt;code&gt;lookup&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lookup&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lookup&lt;/span&gt; k m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; i a)
    | k == i    = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y  l r)
    | outside k x y = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    | insideR r x y = go r
    | otherwise     = go l
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE lookup #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;lookup&lt;/code&gt; can now use the smarter &lt;code&gt;outside&lt;/code&gt; check to fail faster than it can in stock &lt;code&gt;containers&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;insert&quot;&gt;Insert&lt;/h2&gt;
&lt;p&gt;Defining &lt;code&gt;insert&lt;/code&gt; showcases the need for all 6 cases from &lt;code&gt;classify&lt;/code&gt;. You can identify them in the reasoning below for how to handle the &lt;code&gt;Bin&lt;/code&gt; case.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; k a m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a
  go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k j (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a) (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b)
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; j k (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b) (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a)
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a) n
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (go l) r
    | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a)
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k l (go r)
    | significant k y x y = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l (go r)
    | otherwise           = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y (go l) r
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;delete&quot;&gt;Delete&lt;/h2&gt;
&lt;p&gt;We can also define &lt;code&gt;delete&lt;/code&gt;, benefiting similarly from the earlier exit in the unnecessary deletion case:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; r = r
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; y l@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x _) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; y l@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x _ _ _) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE newx #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; _ l &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = l
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; x l r@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; y _)     = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; x l r@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ y _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE newy #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;delete&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;delete&lt;/span&gt; k m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | outside k x y = n
    | insideR k x y = newy x l (go r)
    | otherwise     = newx y (go l) r
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a)
    | k == x    = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
    | otherwise = n
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE delete #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we suffer ever so slightly. The Prefix and Mask are fixed when we call bin in the old code, but now we need to inspect the values we're given in newx and newy to find their bounds.&lt;/p&gt;
&lt;h2 id=&quot;at&quot;&gt;At&lt;/h2&gt;
&lt;p&gt;Finally, no post of mine would be complete without at least one reference to &lt;code&gt;lens&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can define the new &lt;code&gt;alterF&lt;/code&gt; Lens that is being backported to &lt;code&gt;containers&lt;/code&gt; for our modified &lt;code&gt;IntMap&lt;/code&gt; directly. Here I'll call it &lt;code&gt;at&lt;/code&gt;, due to its similarity to the &lt;code&gt;lens&lt;/code&gt; combinator of the same name.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt; k f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;       = maybe &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k x &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k x (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b) n) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; maybe &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) &amp;lt;$&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a)
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b) n) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (min k x) y (insert k b l) r) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x (max k y) l (insert k b r)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    | insideR k x y = newy x l &amp;lt;$&amp;gt; go r
    | otherwise     = (\l' -&amp;gt; newx y l' r) &amp;lt;$&amp;gt; go l
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE at #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can view the scarier, but Haskell 98 type for at in the definition above as&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lens'&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This combinator is a bit hideous, but it &lt;em&gt;should&lt;/em&gt; work! Feel free to test it. =)&lt;/p&gt;
&lt;h2 id=&quot;run-it&quot;&gt;Run It!&lt;/h2&gt;
&lt;p&gt;Putting it all together we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;outside&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Foldable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Traversable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;lookup&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; a
  | &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a) !(&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a)
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt; _   = &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE null #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;empty&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE empty #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;           = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; i a)     = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (i,i)
&lt;span class=&quot;hljs-title&quot;&gt;range&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; i j _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (i,j)
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE range #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  traverse f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y &amp;lt;$&amp;gt; go l &amp;lt;*&amp;gt; go r
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x &amp;lt;$&amp;gt; f a
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = pure &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE traverse #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  foldMap f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = mempty
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; _ a) = f a
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ _ l r) = mappend (go l) (go r)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE foldMap #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
    go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x (f a)
    go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y (go l) (go r)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE fmap #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- @significant a b c d@ implies that the position of the most significant difference between&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @c@ and @d@ dominates the position of the difference between @a and b@.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;significant&lt;/span&gt; a b c d = ab &amp;lt; cd &amp;amp;&amp;amp; ab &amp;lt; xor ab cd &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  cd = xor c d
  ab = xor a b
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE significant #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | for expository purposes only&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt;&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;FarLeft&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearLeft&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InLeft&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;-- within the left branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;InRight&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;-- within the right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;NearRight&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on the same msb, but outside current right branch&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;FarRight&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- differs on a higher msb, outside right branch&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | classify a key @k@ with regards to a binary tree split on the 2-fattest number within @(x..y]@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;classify&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;classify&lt;/span&gt; k x y
  | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FarLeft&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NearLeft&lt;/span&gt;
  | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FarRight&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NearRight&lt;/span&gt;
  | significant k y x y = &lt;span class=&quot;hljs-type&quot;&gt;InRight&lt;/span&gt;
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;InLeft&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE classify #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;outside&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;outside&lt;/span&gt; k x y = k &amp;lt; x || k &amp;gt; y
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE outside #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;insideR&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;insideR&lt;/span&gt; k x y = significant k y x y
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE insideR #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lookup&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lookup&lt;/span&gt; k m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; i a)
    | k == i    = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a
    | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y  l r)
    | outside k x y = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- short-circuit&lt;/span&gt;
    | insideR k x y = go r
    | otherwise     = go l
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE lookup #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;insert&lt;/span&gt; k a m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a
  go (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k j (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a) (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b)
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; j k (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; j b) (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a)
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a) n
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (go l) r
    | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k a)
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k l (go r)
    | significant k y x y = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l (go r)
    | otherwise           = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y (go l) r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE insert #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; r = r
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; y l@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x _) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;newx&lt;/span&gt; y l@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x _ _ _) r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE newx #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; _ l &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = l
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; x l r@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; y _)     = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;newy&lt;/span&gt; x l r@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ y _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE newy #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;delete&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;delete&lt;/span&gt; k m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | outside k x y = n
    | insideR k x y = newy x l (go r)
    | otherwise     = newx y (go l) r
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a)
    | k == x    = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
    | otherwise = n
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE delete #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a)) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;at&lt;/span&gt; k f m0 = go m0 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;       = maybe &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x a) = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare k x &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k x (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b) n) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; maybe &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k) &amp;lt;$&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a)
    &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
  go n@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r)
    | k &amp;gt; y = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y x k &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x k n (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;               &lt;span class=&quot;hljs-comment&quot;&gt;-- far right&lt;/span&gt;
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x (max k y) l (insert k b r)) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- near right&lt;/span&gt;
    | k &amp;lt; x = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; significant x y k y &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; k y (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; k b) n) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;               &lt;span class=&quot;hljs-comment&quot;&gt;-- far left&lt;/span&gt;
                                     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; maybe n (\b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (min k x) y (insert k b l) r) &amp;lt;$&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- near left&lt;/span&gt;
    | significant k y x y = newy x l &amp;lt;$&amp;gt; go r &lt;span class=&quot;hljs-comment&quot;&gt;-- in right&lt;/span&gt;
    | otherwise           = (\l' -&amp;gt; newx y l' r) &amp;lt;$&amp;gt; go l &lt;span class=&quot;hljs-comment&quot;&gt;-- in left&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE at #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = l
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; r = r
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x _)     r@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; y _)     = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; x _)     r@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ y _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x _ _ _) r@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; _ y _ _) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l@(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x _ _ _) r@(&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; y _)     = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y l r
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE bin #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- show Run it!&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ (empty &amp;amp; at &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; ?~ &lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt; &amp;amp; at &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; ?~ &lt;span class=&quot;hljs-string&quot;&gt;&quot;world&quot;&lt;/span&gt;) ^. at &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have no idea if this is faster than the approach taken by &lt;code&gt;Data.IntMap&lt;/code&gt; in practice on real data, but &lt;code&gt;xor&lt;/code&gt; is your friend.&lt;/p&gt;
&lt;p&gt;A great opportunity for participation would be to prove whether this code is faster or slower than the code in &lt;code&gt;Data.IntMap&lt;/code&gt; in practice and if it proves to be faster, flesh it out!&lt;/p&gt;
&lt;p&gt;I have one last diversion I need to post about before I can finally get to talking about the algorithm that started this discussion.&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 23 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part III: Extending Vector</title><link>https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/</link><guid isPermaLink="false">https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/</guid><pubDate>Sun, 25 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 August 2013&lt;/p&gt;&lt;p&gt;As before, if you haven't already, I'd highly recommend reading parts &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/&quot;&gt;1&lt;/a&gt; and &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;2&lt;/a&gt; before proceeding. That said, if you ignore the motivation for the sorting, this post largely stands alone as a practicum on how to extend the &lt;code&gt;vector&lt;/code&gt; package with a custom &lt;code&gt;Vector&lt;/code&gt; type and custom stream fusion combinators.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All&lt;/strong&gt; of the No-Prizes from the previous post are still available! That said, &lt;a href=&quot;http://www.reddit.com/user/ssylvan&quot;&gt;ssyvlan&lt;/a&gt; on reddit was quite helpful in discussions about how to do the leading zero count more efficiently.&lt;/p&gt;
&lt;p&gt;There is only one No-Prize opportunity in this post simply because it otherwise is a fairly simple engineering exercise, and other than that one point I can't think of open questions I have about this code.&lt;/p&gt;
&lt;h2 id=&quot;vector&quot;&gt;Vector&lt;/h2&gt;
&lt;p&gt;Now that we have Morton keys, I finally want to at least be able to &lt;em&gt;represent&lt;/em&gt; a sparse matrix.&lt;/p&gt;
&lt;p&gt;When I think speed in Haskell, I think &lt;code&gt;vector&lt;/code&gt;, &lt;code&gt;repa&lt;/code&gt;, or &lt;code&gt;accelerate&lt;/code&gt;. Today I'm going to focus on &lt;code&gt;vector&lt;/code&gt;, because I think it is the easiest to adapt to suit my purposes.&lt;/p&gt;
&lt;p&gt;Roman Leshchinskiy, author of &lt;code&gt;vector&lt;/code&gt; is probably the single most dedicated disciple of speed I can think of in the Haskell community today. I pay lip service to speed, but he'll sit there and spend weeks fixing any single thing that he can't optimize away into a tight c-like loop. If we're going to try to be competitive with a more traditonal language implementation in the end, we'll want to piggyback on his efforts. Any loss of speed due to stupid misuses of his tools, on the other hand, will entirely be my fault.&lt;/p&gt;
&lt;p&gt;One of the main things that &lt;code&gt;vector&lt;/code&gt; gives us is the power of &lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.104.7401&quot;&gt;stream fusion&lt;/a&gt;. That is to say that if you build a &lt;code&gt;Vector&lt;/code&gt; and then immediately consume it, the &lt;code&gt;vector&lt;/code&gt; library is often smart enough to never bother to construct the intermediate &lt;code&gt;Vector&lt;/code&gt; at all! As we multiply we'll be merging and concatenating streams of values. It is nice to know we can avoid building huge arrays in the interim.&lt;/p&gt;
&lt;p&gt;Again, as I merely pay lip service to the speed God and don't attend services regularly, I'll be going through the motions with a couple of custom stream fusion combinators later on, but I've done rather poor software engineering in that I haven't bothered to check that I needed them. I'd be truly surprised if that turned out not to be the case though.&lt;/p&gt;
&lt;p&gt;Sadly, the vocabulary of &lt;code&gt;Vector&lt;/code&gt; here is somewhat overloaded, so from here out when I talk about a &lt;code&gt;Vector&lt;/code&gt;, unless I explicitly state otherwise, I mean the concept of &lt;code&gt;Vector&lt;/code&gt; from &lt;code&gt;Data.Vector&lt;/code&gt;. If it isn't clear from context then, I'll try to pretend the following imports are in scope:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Boxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Generic
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Primitive &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Primitive
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Storable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Storable

&lt;span class=&quot;hljs-comment&quot;&gt;-- show These will also occur in code samples&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic.Mutable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; GM
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; G
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Stream


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;Those modules still exist!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;... that way if I talk about an &lt;code&gt;Unboxed.Vector&lt;/code&gt; it should make some sense.&lt;/p&gt;
&lt;h2 id=&quot;sorting-out-vectors&quot;&gt;Sorting out Vectors&lt;/h2&gt;
&lt;p&gt;The reason I want to use &lt;code&gt;vector&lt;/code&gt; is that I want my storage to be arranged contiguously in memory whenever possible. Moreover, it enables me to use Dan Doel's excellent &lt;code&gt;vector-algorithms&lt;/code&gt; to manipulate the the Vector of &lt;code&gt;(Key,Value)&lt;/code&gt; pairs in our sparse matrices.&lt;/p&gt;
&lt;p&gt;This comes up right away when we start to try to build a sparse matrix, as I want to sort my sparse matrices by &lt;code&gt;Key&lt;/code&gt; in Morton order, and &lt;code&gt;vector-algorithms&lt;/code&gt; provides me with a large number of sorting algorithms to experiment with, including the fastest &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector-algorithms/0.5.4.2/doc/html/Data-Vector-Algorithms-Intro.html&quot;&gt;intro sort&lt;/a&gt; available in Haskell today. Moreover, it also includes an &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector-algorithms/0.5.4.2/doc/html/Data-Vector-Algorithms-AmericanFlag.html&quot;&gt;american flag&lt;/a&gt; sort that could be used to gain asymptotically on the initial insertion by using the fact that we can not only compare but tell you the bit position at which our keys differ, even if we use variable length keys. This means we're not limited to the asymptotics of a &lt;code&gt;comparison sort&lt;/code&gt; when constructing our initial matrices.&lt;/p&gt;
&lt;p&gt;Dan's sorts rely very heavily on aggressive inlining to get worker-wrapper transforms to fire and to ensure that things like the comparisons done inside the sorting routine are being passed unboxed values.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;vector&lt;/code&gt; and &lt;code&gt;vector-algorithms&lt;/code&gt; leads to our first stumbling block.&lt;/p&gt;
&lt;p&gt;What I want to do is store a &lt;code&gt;Vector (Key, a)&lt;/code&gt; in such a way that I can have unboxed keys. However, I don't want to lose the flexibility to have unboxed values!&lt;/p&gt;
&lt;p&gt;To that end, when I started this project about a week ago, I pushed out a &lt;a href=&quot;https://hackage.haskell.org/package/hybrid-vectors&quot;&gt;&lt;code&gt;hybrid-vectors&lt;/code&gt;&lt;/a&gt; package to &lt;a href=&quot;https://hackage.haskell.org/packages/hackage.html&quot;&gt;hackage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As it'll be the glue that holds together our matrix representation until I find something better, I felt it made sense to say a few words motivating its construction.&lt;/p&gt;
&lt;h2 id=&quot;unboxed-vectors&quot;&gt;Unboxed Vectors&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;vector&lt;/code&gt; is already quite smart about managing storage. In particular an unboxed &lt;code&gt;Vector&lt;/code&gt; of pairs is managed as a pair of vectors of the individual parts. Anybody who has done much GPU work will recognize this as the &lt;em&gt;structure of arrays&lt;/em&gt; (&lt;strong&gt;SoA&lt;/strong&gt;) approach that is often used there rather than &lt;em&gt;array of structures&lt;/em&gt; (&lt;strong&gt;AoS&lt;/strong&gt;) approach used more traditionally throughout the rest of the industry.&lt;/p&gt;
&lt;p&gt;In case you've never thought about it before, it is worth mentioning that it has many benefits. One of those benefits is that you don't pay cache storage for parts of the structure you don't look at. You also don't incur unnecessary time/space trade-offs for alignment issues, etc. The cache dominates most concerns about slightly more complicated addressing logic, and if you look at things like the x86 instruction set, the addressing logic usually simplifies as well! We can calculate the &lt;code&gt;\*{1,2,4,8}&lt;/code&gt; multiplier in the index &lt;em&gt;en passant&lt;/em&gt;, but the odd sizes you get in &quot;array of structures&quot; are usually not so easy to use.&lt;/p&gt;
&lt;p&gt;All of this is well and good, but I can't just use &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector-Unboxed.html&quot;&gt;&lt;code&gt;Data.Vector.Unboxed&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My particular motivation for working on this code in the first place requires me to be able to do matrix multiplication over certain fairly complicated ring-like structures that I can't &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector-Unboxed.html#t:Unbox&quot;&gt;&lt;code&gt;Unbox&lt;/code&gt;&lt;/a&gt;. I say &quot;ring-like&quot; because right seminearrings without &lt;a href=&quot;http://en.wikipedia.org/wiki/Zero_divisor&quot;&gt;zero-divisors&lt;/a&gt; arise in various forms of &lt;a href=&quot;http://en.wikipedia.org/wiki/Chart_parser&quot;&gt;chart parsing&lt;/a&gt;, and &lt;a href=&quot;http://www.cse.chalmers.se/~bernardy/PP.pdf&quot;&gt;some&lt;/a&gt; are even &lt;a href=&quot;http://en.wikipedia.org/wiki/Nonassociative_ring&quot;&gt;non-associative&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;hybrid-vectors&quot;&gt;Hybrid Vectors&lt;/h2&gt;
&lt;p&gt;Fortunately, in a great feat of engineering, Roman left the entire &lt;code&gt;Vector&lt;/code&gt; framework open to extension with new &lt;code&gt;Vector&lt;/code&gt; types, by providing us with &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector-Generic.html&quot;&gt;&lt;code&gt;Data.Vector.Generic&lt;/code&gt;&lt;/a&gt; and moreover, he made it so that the entire stream fusion framework he uses will just magically work with any instance of &lt;a href=&quot;https://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector-Generic.html#t:Vector&quot;&gt;&lt;code&gt;Generic.Vector&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So all we need to do is define our own &lt;code&gt;Vector&lt;/code&gt; (and &lt;code&gt;MVector&lt;/code&gt;) type for the kinds of &quot;hybrid&quot; vectors we need.&lt;/p&gt;
&lt;p&gt;Then Dan's fast sorting algorithms can be used out of the box and we can steal and extend Roman's fusion framework.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Data.Vector.Unboxed&lt;/code&gt; has already shown us the way to build an SoA-style vector. We just need it to be more permissive about what kind of &lt;code&gt;Generic.Vector&lt;/code&gt; vectors are allowed to comprise each side.&lt;/p&gt;
&lt;p&gt;To define a &lt;code&gt;Generic.Vector&lt;/code&gt;, first we must define &lt;code&gt;Generic.MVector&lt;/code&gt; that'll be used for most operations involved in building or manipulating it behind the scenes.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE CPP #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GeneralizedNewtypeDeriving #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE KindSignatures #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveDataTypeable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ScopedTypeVariables #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic.Mutable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; GM
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; G
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Stream
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Data
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; ( &lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;replicate&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;reverse&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;map&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;read&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;take&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;drop&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;init&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;tail&lt;/span&gt; )
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Read

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; :: (* -&amp;gt; * -&amp;gt; *) -&amp;gt; (* -&amp;gt; * -&amp;gt; *) -&amp;gt; * -&amp;gt; * -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; :: !(u s a) -&amp;gt; !(v s b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; u v s (a, b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  basicLength (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks _) = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicLength ks
  basicUnsafeSlice s e (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) = &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeSlice s e ks) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeSlice s e vs)
  basicOverlaps (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicOverlaps ks ks' || &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicOverlaps vs vs'
  basicUnsafeNew n = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeNew n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeNew n)
  basicUnsafeReplicate n (k,v) = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeReplicate n k) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeReplicate n v)
  basicUnsafeRead (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n = liftM2 (,) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeRead ks n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeRead vs n)
  basicUnsafeWrite (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n (k,v) = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeWrite ks n k &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeWrite vs n v
  basicClear (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicClear ks &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicClear vs
  basicSet (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (k,v) = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicSet ks k &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicSet vs v
  basicUnsafeCopy (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeCopy ks ks' &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeCopy vs vs'
  basicUnsafeMove (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeMove ks ks' &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeMove vs vs'
  basicUnsafeGrow (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeGrow ks n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeGrow vs n)

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, so it must be correct.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we've done is say that our &lt;code&gt;Hybrid.MVector u v s (a,b)&lt;/code&gt; is going to be comprised (strictly!) of two other vectors &lt;code&gt;u s a&lt;/code&gt; and &lt;code&gt;v s b&lt;/code&gt; so long as we have appropriate &lt;code&gt;Generic.MVector&lt;/code&gt; instances to rely upon, and so long as they can both be manipulated in the same &lt;a href=&quot;https://hackage.haskell.org/packages/archive/primitive/0.5.0.1/doc/html/Control-Monad-Primitive.html#t:PrimMonad&quot;&gt;&lt;code&gt;PrimMonad&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All we've done is borrow from similar operations from the vectors that comprise our constituent parts.&lt;/p&gt;
&lt;p&gt;In the real code we then proceed to &lt;code&gt;INLINE&lt;/code&gt; everything in sight, so that any inlined combinators from &lt;code&gt;Data.Vector.Generic&lt;/code&gt; can &quot;see through&quot; our &lt;code&gt;instance&lt;/code&gt; and &lt;code&gt;INLINE&lt;/code&gt; the bodies of our methods.&lt;/p&gt;
&lt;p&gt;We can construct a custom &lt;code&gt;Generic.Vector&lt;/code&gt; similarly.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# START_FILE Hybrid.hs #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE CPP #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GeneralizedNewtypeDeriving #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE KindSignatures #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveDataTypeable #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE ScopedTypeVariables #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Hybrid &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic.Mutable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; GM
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; G
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Stream
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Data
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; ( &lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;null&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;replicate&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;reverse&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;map&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;read&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;take&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;drop&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;init&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;tail&lt;/span&gt; )
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Read

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; :: (* -&amp;gt; * -&amp;gt; *) -&amp;gt; (* -&amp;gt; * -&amp;gt; *) -&amp;gt; * -&amp;gt; * -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; :: !(u s a) -&amp;gt; !(v s b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; u v s (a, b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  basicLength (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks _) = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicLength ks
  basicUnsafeSlice s e (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) = &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeSlice s e ks) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeSlice s e vs)
  basicOverlaps (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicOverlaps ks ks' || &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicOverlaps vs vs'
  basicUnsafeNew n = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeNew n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeNew n)
  basicUnsafeReplicate n (k,v) = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeReplicate n k) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeReplicate n v)
  basicUnsafeRead (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n = liftM2 (,) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeRead ks n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeRead vs n)
  basicUnsafeWrite (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n (k,v) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeWrite ks n k
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeWrite vs n v
  basicClear (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicClear ks
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicClear vs
  basicSet (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (k,v) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicSet ks k
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicSet vs v
  basicUnsafeCopy (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeCopy ks ks'
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeCopy vs vs'
  basicUnsafeMove (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeMove ks ks'
    &lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeMove vs vs'
  basicUnsafeGrow (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) n = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeGrow ks n) (&lt;span class=&quot;hljs-type&quot;&gt;GM&lt;/span&gt;.basicUnsafeGrow vs n)

  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicLength #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeSlice #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicOverlaps #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeNew #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeReplicate #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeRead #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeWrite #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicClear #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicSet #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeCopy #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeMove #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeGrow #-}&lt;/span&gt;


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; :: (* -&amp;gt; *) -&amp;gt; (* -&amp;gt; *) -&amp;gt; * -&amp;gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; :: !(u a) -&amp;gt; !(v b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; u v (a, b)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; instance &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Mutable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;MVector&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Mutable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Mutable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  basicUnsafeFreeze (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeFreeze ks) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeFreeze vs)
  basicUnsafeThaw (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks vs) = liftM2 &lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeThaw ks) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeThaw vs)
  basicLength (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks _) = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicLength ks
  basicUnsafeSlice i j (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks vs) = &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeSlice i j ks) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeSlice i j vs)
  basicUnsafeIndexM (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks vs) n = liftM2 (,) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeIndexM ks n) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeIndexM vs n)
  basicUnsafeCopy (&lt;span class=&quot;hljs-type&quot;&gt;MV&lt;/span&gt; ks vs) (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks' vs') = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeCopy ks ks'
    &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.basicUnsafeCopy vs vs'
  elemseq (&lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; ks vs) (k,v) b = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.elemseq ks k (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.elemseq vs v b)

  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeFreeze #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeThaw #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicLength #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeSlice #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeIndexM #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE basicUnsafeCopy #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE elemseq #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mappend = (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.++)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE mappend #-}&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.empty
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE mempty #-}&lt;/span&gt;
  mconcat = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.concat
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE mconcat #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  showsPrec = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.showsPrec
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  readPrec = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.readPrec
  readListPrec = readListPrecDefault
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xs == ys = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.eq (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys)
  xs /= ys = not (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.eq (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys))
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE (==) #-}&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE (/=) #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare xs ys = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.cmp (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys)
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE compare #-}&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;{-# START_FILE Main.hs #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Main &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Hybrid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Boxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Generic
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Unboxed &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Unboxed
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Primitive &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Primitive
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Storable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Storable
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic.Mutable &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; GM
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.Vector.Generic &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; G
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Stream


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Hybrid&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Boxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  print (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.fromList [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;)] :: &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt;)
  print $ &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.slice &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.fromList (&lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.zip [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;] [&lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;20&lt;/span&gt;]) :: &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is worth taking a couple of minutes to talk about the instances, though.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Generic.Vector&lt;/code&gt; types typically provide the obvious &lt;code&gt;Monoid&lt;/code&gt;, &lt;code&gt;Show&lt;/code&gt;, &lt;code&gt;Read&lt;/code&gt;, &lt;code&gt;Eq&lt;/code&gt;, and &lt;code&gt;Ord&lt;/code&gt; instances we've come to expect.&lt;/p&gt;
&lt;p&gt;But if we were not careful and wrote&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;))
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then the compiler would be unduly reticent to use the instance. That is, it won't realize that the moment it can see that we have a &lt;code&gt;Hybrid.Vector&lt;/code&gt;, that the argument must be a pair as, after all, our GADT only has one constructor!&lt;/p&gt;
&lt;p&gt;So instead we need to write the remaining instances to abuse the power of &lt;a href=&quot;http://research.microsoft.com/en-us/um/people/simonpj/papers/ext-f/&quot;&gt;system Fc&lt;/a&gt; and modern Haskell to say that once the compiler figures out it needs one of these instances for a &lt;code&gt;Hybrid.Vector u v c&lt;/code&gt; it can infer &lt;code&gt;c&lt;/code&gt; must be of the form &lt;code&gt;(a,b)&lt;/code&gt; by writing these instances as&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mappend = (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.++)
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.empty
  mconcat = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.concat
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  showsPrec = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.showsPrec
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  readPrec = &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.readPrec
  readListPrec = readListPrecDefault
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Ord&lt;/code&gt; we need to lean a little bit on the fusion machinery, just because no such defaults are provided for us.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xs == ys = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.eq (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys)
  xs /= ys = not (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.eq (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; ~ (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare xs ys = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt;.cmp (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream xs) (&lt;span class=&quot;hljs-type&quot;&gt;G&lt;/span&gt;.stream ys)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we finally have everything we need for our &lt;code&gt;Hybrid.Vector&lt;/code&gt; type to feel like a real &lt;code&gt;Vector&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;OK, not quite &lt;em&gt;everything&lt;/em&gt;, for reasons that I'm sure make sense to Roman, he goes and duplicates the entire &lt;code&gt;vector&lt;/code&gt; API individually customized to each vector subtype within their own modules. Admittedly, it does help with inference in the presence of such an all encompassing API that can both produce and consume values of the same type. To that end, &lt;code&gt;hybrid-vectors&lt;/code&gt; includes a couple thousand lines of boilerplate as well to make a &lt;code&gt;vector&lt;/code&gt; programmer feel at home. It also contains another, related notion, that of a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/hybrid-vectors/0.1/doc/html/Data-Vector-Mixed.html&quot;&gt;&lt;code&gt;Mixed.Vector&lt;/code&gt;&lt;/a&gt; that permits more operations to cooperate across vector types, as it was something that was easy to implement while I had all of the &lt;code&gt;vector&lt;/code&gt; internals paged in mentally.&lt;/p&gt;
&lt;p&gt;However, the details of that implementation is entirely mechanical.&lt;/p&gt;
&lt;p&gt;Similarly, we need to go through a similar boilerplate exercise making an instance of &lt;code&gt;Unbox&lt;/code&gt; for &lt;code&gt;Key&lt;/code&gt;, but nothing new is learned.&lt;/p&gt;
&lt;h2 id=&quot;custom-stream-fusion&quot;&gt;Custom Stream Fusion&lt;/h2&gt;
&lt;p&gt;Before we move on, we are going to need at least one custom stream fusion combinator for adding two matrices together.&lt;/p&gt;
&lt;p&gt;I don't want to pre-judge that all addition will fall under the purview of the &lt;code&gt;Num&lt;/code&gt; typeclass, as for instance since we're sparse we can use &lt;code&gt;Mat Unboxed.Vector ()&lt;/code&gt; as a Boolean matrix and pay surprisingly little overhead as an &lt;code&gt;Unboxed.Vector&lt;/code&gt; of &lt;code&gt;()&lt;/code&gt;s is represented simply by its &lt;code&gt;size&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Consequently, let's define a generalized merge operation that can permit values to cancel.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mergeStreamsWith&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; i)
  =&amp;gt; (a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;Vector&lt;/code&gt;'s current version of monadic stream fusion, a &lt;code&gt;Stream&lt;/code&gt; consists of a step function, a state, and any knowledge we have about the &lt;code&gt;Size&lt;/code&gt; of the &lt;code&gt;Stream&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m a = forall s . &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) s &lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore with an appropriate new &lt;code&gt;step&lt;/code&gt; function, we can write:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mergeStreamsWith&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; stepa sa0 na) (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; stepb sb0 nb)
  = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; step (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa0 sb0) (toMax na + toMax nb)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here our starting state &lt;code&gt;MergeStart&lt;/code&gt; is described below, and we convert the bounds we know on the input streams into a conservative upper bound on our new stream size.&lt;/p&gt;
&lt;p&gt;Stream fusion works by ensuring that each &lt;code&gt;Step&lt;/code&gt; you take does not recurse, so the compiler is able to move all of the iteration to one outer-most loop.&lt;/p&gt;
&lt;p&gt;At each &lt;code&gt;Step&lt;/code&gt;, we can &lt;code&gt;Yield&lt;/code&gt; a new answer and switch to a new state, simply switch to a new state or terminate our &lt;code&gt;Stream&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Step&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; a s | &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; s | &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In our case we need to consume from two other streams, but we can only afford to ask for a bounded amount of work from each at each &lt;code&gt;Step&lt;/code&gt;. So let's build a custom state type for our &lt;code&gt;Stream&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MergeState&lt;/span&gt; sa sb i a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb i a
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb i a
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll want to reason through our &lt;code&gt;step&lt;/code&gt; function by cases as it is rather tedious.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MergeStart&lt;/code&gt; is our initial state, consisting of the initial states of both of our input streams.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa' sb i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We try to read from the left stream. If it succeeds we know the value from the left stream (and are in state &lt;code&gt;MergeL&lt;/code&gt;). If it skips we have to try again. If it says it has no more content, we should fast forward through the right hand stream with &lt;code&gt;MergeLeftEnded&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the logic follows similarly.&lt;/p&gt;
&lt;p&gt;Once we have a value from our left &lt;code&gt;Stream&lt;/code&gt;, we should try to read from our right, merging values if their indices are equal, and otherwise putting them in order. Depending on which candidate was merged, we proceed to &lt;code&gt;MergeR&lt;/code&gt; or &lt;code&gt;MergeL&lt;/code&gt;. If during the &lt;code&gt;Merge&lt;/code&gt;, we determine that our elements cancelled out, e.g. &lt;code&gt;5 + (-5)&lt;/code&gt;, thn rather than recurse into start to ensure a bounded amount of work is done, we &lt;code&gt;Skip&lt;/code&gt; back there.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb i a) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepb sb
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) sb' -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb' j b)
        &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
           &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; c  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, c) (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb')
           &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb')
        &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb' i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sb' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb' i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;MergeR&lt;/code&gt; is entirely symmetric to &lt;code&gt;MergeL&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb j b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa' sb j b)
        &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
          &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; c  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, c) (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
          &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
        &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa' sb i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa' sb j b)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then we just have to deal with fast forwarding:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepb sb
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) sb' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb')
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sb'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb')
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa')
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa')
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Putting it all together we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream.Monadic (&lt;span class=&quot;hljs-type&quot;&gt;Step(..)&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Stream(..)&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Vector.Fusion.Stream.Size

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MergeState&lt;/span&gt; sa sb i a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb i a
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb i a
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa
  | &lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb

&lt;span class=&quot;hljs-title&quot;&gt;mergeStreamsWith&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; i)
  =&amp;gt; (a -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; m (i, a)
&lt;span class=&quot;hljs-title&quot;&gt;mergeStreamsWith&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; stepa sa0 na) (&lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; stepb sb0 nb)
  = &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; step (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa0 sb0) (toMax na + toMax nb) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa' sb i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb)
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb i a) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepb sb
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) sb' -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb' j b)
        &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
           &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; c  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, c) (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb')
           &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa sb')
        &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb' i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sb' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa sb' i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa)
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa sb j b) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; compare i j &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;LT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa' sb j b)
        &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; f a b &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
          &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; c  -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, c) (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
          &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeStart&lt;/span&gt; sa' sb)
        &lt;span class=&quot;hljs-type&quot;&gt;GT&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b)     (&lt;span class=&quot;hljs-type&quot;&gt;MergeL&lt;/span&gt; sa' sb i a)
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeR&lt;/span&gt; sa' sb j b)
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb)
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepb sb
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) sb' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (j, b) (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb')
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sb'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeLeftEnded&lt;/span&gt; sb')
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  step (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa) = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    r &amp;lt;- stepa sa
    return $ &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; r &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) sa' -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; (i, a) (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa')
      &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; sa'         -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Skip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;MergeRightEnded&lt;/span&gt; sa')
      &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;             -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [0] step #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE [1] mergeStreamsWith #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;That compiles, too.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is worth noting the phase-controlled &lt;code&gt;INLINE&lt;/code&gt; pragmas in the final definition as well. Without them you really won't see much benefit from stream fusion! They ensure that the compiler is careful to hold onto the steps uninlined until the right moment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize #6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It'd probably be much more efficient for us to us an efficient &lt;code&gt;k-merge&lt;/code&gt; or, even better, a cache-oblivious
variant that is careful to make no assumptions about our caches. The only two operations we'll be using
&lt;code&gt;Stream&lt;/code&gt; fusion for are concatenation and &lt;code&gt;mergeStreamsWith&lt;/code&gt; for now. Is there a more efficient fusion form we should be using that can exploit this structure?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;matrices-not-vectors&quot;&gt;Matrices, not Vectors&lt;/h2&gt;
&lt;p&gt;Now that we have &lt;code&gt;hybrid-vectors&lt;/code&gt;, we can &lt;em&gt;finally&lt;/em&gt; peek at what our matrix representation can look like.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mat&lt;/span&gt; v a = &lt;span class=&quot;hljs-type&quot;&gt;Mat&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runMat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Hybrid&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Unboxed&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;v&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and how we could build one:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Generic&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Vector&lt;/span&gt; v a =&amp;gt; [(&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;, a)] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mat&lt;/span&gt; v a
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; xs
  = &lt;span class=&quot;hljs-type&quot;&gt;Mat&lt;/span&gt;
  $ &lt;span class=&quot;hljs-type&quot;&gt;Generic&lt;/span&gt;.modify (&lt;span class=&quot;hljs-type&quot;&gt;Intro&lt;/span&gt;.sortBy (compare `on` fst))
  $ &lt;span class=&quot;hljs-type&quot;&gt;Generic&lt;/span&gt;.fromList xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we'll see next time don't need type parameters for the number of dimensions and we don't need to store information on the dimensionality of the contents as well as we'll be able to turn back to the notions of &quot;most significant most significant difference&quot; and 2-fattest numbers a second time.&lt;/p&gt;
&lt;p&gt;And you'd hoped the bit-twiddling was behind us. Hah!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;August 18, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part II: The Zen of Z-Ordering</title><link>https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/</link><guid isPermaLink="false">https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/</guid><pubDate>Sun, 25 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 August 2013&lt;/p&gt;&lt;p&gt;If you haven't already, you'll want to read &lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/&quot;&gt;Revisiting Matrix Multiplication, Part I&lt;/a&gt; before proceeding.&lt;/p&gt;
&lt;p&gt;I've posted the result from the first 2 No-Prizes inline in the original post, with the spoilers being hidden.&lt;/p&gt;
&lt;h2 id=&quot;a-most-significant-difference&quot;&gt;A Most Significant Difference&lt;/h2&gt;
&lt;p&gt;As anyone who read through &lt;a href=&quot;http://en.wikipedia.org/wiki/Z-order_curve&quot;&gt;the wikipedia article on Z-order curves&lt;/a&gt; for spoilers can tell you, it turns out we don't have to actually interleave the bits if all we want is the ability to compare two keys &lt;em&gt;as if&lt;/em&gt; they had been interleaved.&lt;/p&gt;
&lt;p&gt;What we need to know is where the most significant difference between them occurs.&lt;/p&gt;
&lt;p&gt;Given two halves of a key we can exclusive or them together to find the positions at which they differ.&lt;/p&gt;
&lt;p&gt;I'll call the mask with only the most significant bit (&lt;code&gt;msb&lt;/code&gt;) of this mask set their &quot;most significant difference&quot; (&lt;code&gt;msd&lt;/code&gt;) and that position as indicating the &quot;critical bit&quot; if it exists.&lt;/p&gt;
&lt;p&gt;One way to compute that most significant difference is to first &quot;smear&quot; all of the bits that are set in that mask to the right to get a new mask.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Numeric.Lens

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @smear x@ returns the smallest @2^n-1 &amp;gt;= x@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; k0 = k6 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k1 = k0 .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  k2 = k1 .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  k3 = k2 .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
  k4 = k3 .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
  k5 = k4 .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;
  k6 = k5 .|. unsafeShiftR k5 &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @msb x@ returns the largest @2^n &amp;lt;= x@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; x = y `xor` unsafeShiftR y &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; y = smear x

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @fat x y@ for @x &amp;lt; y@ returns the unique selection of @z = i*2^n@&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- in @x &amp;lt; z &amp;lt;= y@ that maximizes n.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; x y = complement (unsafeShiftR (smear (xor x y)) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) .&amp;amp;. y


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ base &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; # smear &lt;span class=&quot;hljs-number&quot;&gt;0xf001030900&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then we could shift them mask right one place and xor that with the original mask to get the most significant bit as a mask.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Numeric.Lens
&lt;span class=&quot;hljs-comment&quot;&gt;-- | @smear x@ returns the smallest @2^n-1 &amp;gt;= x@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; k0 = k6 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k1 = k0 .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  k2 = k1 .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  k3 = k2 .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
  k4 = k3 .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
  k5 = k4 .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;
  k6 = k5 .|. unsafeShiftR k5 &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- | @msb x@ returns the largest @2^n &amp;lt;= x@&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; x = y `xor` unsafeShiftR y &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; y = smear x

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @fat x y@ for @x &amp;lt; y@ returns the unique selection of @z = i*2^n@&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- in @x &amp;lt; z &amp;lt;= y@ that maximizes n.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; x y = complement (unsafeShiftR (smear (xor x y)) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) .&amp;amp;. y


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  print $ base &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; # msb &lt;span class=&quot;hljs-number&quot;&gt;0xf001030900&lt;/span&gt;
  print $ base &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; # msb (xor &lt;span class=&quot;hljs-number&quot;&gt;0xff0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xc00&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize opportunity #3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;__builtin_clz&lt;/code&gt; can be used to count leading zeros and we can shift that many places. How big of a
performance difference is there in doing it this way vs. doing this with the fiddly masks? I need benchmarks
and performance numbers -- preferably as patches to that shiny new &lt;a href=&quot;https://github.com/ekmett/sparse&quot;&gt;sparse&lt;/a&gt;
repository I mentioned last time as a patch to &lt;a href=&quot;https://github.com/ekmett/bits&quot;&gt;bits&lt;/a&gt; which provides &lt;code&gt;nlz&lt;/code&gt;
for the number of leading zeroes as part of a class in &lt;code&gt;Data.Bits.Extras&lt;/code&gt;. Please feel free to send me pull requests if you find faster ways to do things! We'll need all the speed we can get soon.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-2-fattest-number&quot;&gt;The 2-Fattest Number&lt;/h2&gt;
&lt;p&gt;(You can skip this on first-reading, but it'll be relevant later and we &lt;em&gt;just&lt;/em&gt; introduced all the bits needed to define it.)&lt;/p&gt;
&lt;p&gt;There is another related quantity that we'll need soon when I turn to matrix multiplication that I'd like to point out. It is known as the 2-fattest number in an interval. The 2-fattest number in an interval is the number in that interval that has the largest number of trailing 0s in its binary representation.&lt;/p&gt;
&lt;p&gt;The first time I saw this term was in Djamal Belazzougui et al.'s excellent treatise on &lt;a href=&quot;http://www.itu.dk/people/pagh/papers/sparse.pdf&quot;&gt;Monotone Minimal Perfect Hashing&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Numeric.Lens
&lt;span class=&quot;hljs-comment&quot;&gt;-- | @smear x@ returns the smallest @2^n-1 &amp;gt;= x@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;smear&lt;/span&gt; k0 = k6 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k1 = k0 .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  k2 = k1 .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  k3 = k2 .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
  k4 = k3 .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
  k5 = k4 .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;
  k6 = k5 .|. unsafeShiftR k5 &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @msb x@ returns the largest @2^n &amp;lt;= x@&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;msb&lt;/span&gt; x = y `xor` unsafeShiftR y &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; y = smear x


&lt;span class=&quot;hljs-comment&quot;&gt;-- | @fat x y@ for @x &amp;lt; y@ returns the unique selection of @z = b*2^i@&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- in @x &amp;lt; z &amp;lt;= y@ that maximizes @i@.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fat&lt;/span&gt; x y = complement (unsafeShiftR (smear (xor x y)) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) .&amp;amp;. y


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ base &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; # fat &lt;span class=&quot;hljs-number&quot;&gt;0x1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0xf&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The 2-fattest number for an interval has a number of interesting properties.&lt;/p&gt;
&lt;p&gt;1.) The 2-fattest number &lt;code&gt;z = b*2^i&lt;/code&gt;in an interval &lt;code&gt;[x..y]&lt;/code&gt; is uniquely determined by &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. &lt;em&gt;Proof Sketch&lt;/em&gt; If it were not, then since it the two candidates are odd, there'd exists an even number between them and hence also in the interval, but then that number would be of the form &lt;code&gt;b*2^(i+1)&lt;/code&gt;, violating our claim that either of them was 2-fattest. Note the shift to talking about a closed interval rather than one open on the left.&lt;/p&gt;
&lt;p&gt;2.) It is the least value in the interval for which their most significant differing bit goes from low to high.&lt;/p&gt;
&lt;p&gt;3.) If &lt;code&gt;y - x &amp;lt; 2^i&lt;/code&gt; then there exists at most one &lt;code&gt;b&lt;/code&gt; value for which &lt;code&gt;b*2^i&lt;/code&gt; falls within the interval &lt;code&gt;[x..y]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;4.) If &lt;code&gt;i&lt;/code&gt; is such that &lt;code&gt;[x..y]&lt;/code&gt; does not contain any value of the form &lt;code&gt;b*2^i&lt;/code&gt; then &lt;code&gt;y - x + 1 &amp;lt;= 2^i - 1&lt;/code&gt; and the interval may contain at most one single value of the form &lt;code&gt;b*2^(i-1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most if not all of these properties will be useful to us later on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize opportunity #4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cleanly rewrite those laws in terms of &lt;code&gt;(x..y]&lt;/code&gt;, so I can clean up the exposition above and be the first to send them to me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-only-winning-move&quot;&gt;The Only Winning Move&lt;/h2&gt;
&lt;p&gt;Now that we are so equipped with new bit twiddling tools, we can finally tackle comparing keys for relative ordering by their Morton order without interleaving their bits at all!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The lenses to access the fields become trivial.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _2 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; i j) = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; i &amp;lt;$&amp;gt; indexed f (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) j
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now know how to compute the most significant difference between two key &lt;em&gt;components&lt;/em&gt;. So to compare keys what we want to do is determine which key component has the most significant &quot;most significant difference&quot;.&lt;/p&gt;
&lt;p&gt;We could do that directly by computing the &lt;code&gt;msd&lt;/code&gt; of each key component independently, and then comparing it, and then following up by comparing just the key component that won the toss. This is a fun exercise to do. It is also slightly more general than the construction I'm about to use, as I don't have to have keys with the same word size, and can support variable length keys so long as they have the &lt;a href=&quot;http://en.wikipedia.org/wiki/Prefix_code&quot;&gt;prefix property&lt;/a&gt; enabling me to work with compressed indices, and provides other benefits, but we can perform an equivalent operation with a lot less bit twiddling!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; c d)
    | ac &amp;lt; bd &amp;amp;&amp;amp; ac &amp;lt; xor ac bd = compare b d
    | otherwise                 = compare a c
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      ac = xor a c
      bd = xor b d
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize opportunity #5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Be the first to email me a proof of why this works and see your name immortalized as the proud owner of the 5th No-Prize!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This isn't a pure win as they are a number of operations that can still be performed on the shuffled representation somewhat faster, such as calculating &lt;code&gt;succ&lt;/code&gt; in Morton order.&lt;/p&gt;
&lt;p&gt;Fun Exercise: What does a nice version of &lt;code&gt;succ&lt;/code&gt; or &lt;code&gt;pred&lt;/code&gt; that moves to the next address in Morton order look like in this representation?&lt;/p&gt;
&lt;p&gt;However, this does provide a reference for how we can play around with identifying and using the &quot;most significant most significant difference&quot; in a useful way.&lt;/p&gt;
&lt;p&gt;Putting it all together:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;{-# UNPACK #-}&lt;/span&gt; !&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; c d)
    | ac &amp;lt; bd &amp;amp;&amp;amp; ac &amp;lt; xor ac bd = compare b d
    | otherwise                 = compare a c
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      ac = xor a c
      bd = xor b d
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _1 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b) = (`&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;` b) &amp;lt;$&amp;gt; indexed f (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _2 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a &amp;lt;$&amp;gt; indexed f (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) b


&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;it compiles!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an alternative to the comparison above, we could have checked the if &lt;code&gt;ac .&amp;amp;. msb (ac .|. bd) == 0&lt;/code&gt;. But that relies on &lt;code&gt;msb&lt;/code&gt; being particularly fast to calculate relative to a few &lt;code&gt;xor&lt;/code&gt;s and inequalities. I'm dubious but available to be swayed by benchmarks. Also, I'll need to know if the msb is in an even or odd position later on, so any calculation of it that doesn't let me calculate the msb's position parity won't be very useful.&lt;/p&gt;
&lt;h2 id=&quot;omake-dilated-arithmetic&quot;&gt;Omake: Dilated Arithmetic&lt;/h2&gt;
&lt;p&gt;We could continue to explore alternative alternatives.&lt;/p&gt;
&lt;p&gt;When we extracted &lt;code&gt;_1&lt;/code&gt; and &lt;code&gt;_2&lt;/code&gt; from &lt;code&gt;Key&lt;/code&gt; in the previous article, we bothered to shuffle them into and out of position.&lt;/p&gt;
&lt;p&gt;It turns out that we can support a form of dilated arithmetic directly on them in their shuffled form.&lt;/p&gt;
&lt;p&gt;We could make newtype wrappers around a &lt;code&gt;Word64&lt;/code&gt; for two different dilations.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DilatedEven&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DilatedEven&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DilatedOdd&lt;/span&gt;  = &lt;span class=&quot;hljs-type&quot;&gt;DilatedOdd&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then there is a nice paper by Wise, Frens and Gu on &lt;a href=&quot;http://www.cs.indiana.edu/~dswise/ppopp01.pdf&quot;&gt;Language Support for Morton-order Matrices&lt;/a&gt; that describes how to directly perform dilated arithmetic where the bits you are interested are only in the even or odd bits of a larger number. They further talk about a number of compiler optimizations you may want to perform on these. Some of those optimizations could be implemented with &lt;code&gt;RULES&lt;/code&gt; pragmas.&lt;/p&gt;
&lt;p&gt;I'd be curious to see what anyone comes up with down this path of inquiry.&lt;/p&gt;
&lt;p&gt;In practice we'll see a couple of numbers left in dilated form later, but I haven't (yet!) bothered to write newtypes for them or duplicate Wise et al's arithmetic operators for working on them directly.&lt;/p&gt;
&lt;h2 id=&quot;where-do-we-go-now&quot;&gt;Where Do We Go Now?&lt;/h2&gt;
&lt;p&gt;We'll be abusing &lt;code&gt;smear&lt;/code&gt;, this terminology, the notion of a &quot;most significant most significant difference&quot; and the 2-fattest number in a range when we start to talk about how we might want to decompose matrices. However, next time I need to take a slight detour into talking about how to make a custom &lt;code&gt;Vector&lt;/code&gt; type!&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;
August 16, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Revisiting Matrix Multiplication — Part I: Bit Shuffling with Lenses and Isomorphisms</title><link>https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/</link><guid isPermaLink="false">https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/</guid><pubDate>Sun, 25 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 August 2013&lt;/p&gt;&lt;p&gt;I'm going to try a few new things today.&lt;/p&gt;
&lt;p&gt;First, I'm trying to write a post using the School of Haskell.&lt;/p&gt;
&lt;p&gt;Second, I'm going to try to work through some code in a rather collaborative fashion. That is to say, I have a general idea of where I'm going and how to make it fast, but I have yet to do so and I'd like to actively encourage you to help me figure it out.&lt;/p&gt;
&lt;p&gt;So, what are we hacking on?&lt;/p&gt;
&lt;p&gt;I was recently reminded by Carter Schonwald about some properties of Morton ordering that turned out to be particularly relevant to sparse matrix multiplication. Along the way I discovered a particularly nice formulation of the problem, and I figured it would be a fun way to get my feet wet writing stuff here.&lt;/p&gt;
&lt;p&gt;Hopefully, this series will have a bit of something for everybody: Some lenses, some bit bashing, worries about cache coherence, stream fusion, nice recursion patterns, finding simpler formulations for traditional algorithms, and general functional programming fun.&lt;/p&gt;
&lt;p&gt;I'll also try to call out opportunities for readers to help as I go along. Particularly in the later parts, there will be a lot of room for improvement and many hands make light work!&lt;/p&gt;
&lt;p&gt;The code for this project is available on github at &lt;a href=&quot;https://github.com/ekmett/sparse&quot;&gt;github.com/ekmett/sparse&lt;/a&gt; if you are impatient and want to skip ahead. It isn't quite the last page in a murder mystery, and I haven't been shy about talking about this stuff, but I fully intend to crank away on development in there, so it may get pretty far in advance of these posts -- especially if you are late to the party!&lt;/p&gt;
&lt;p&gt;Later on, we'll get to some numerics, and maybe they'll even perform decently, but today is mostly just setting up key space.&lt;/p&gt;
&lt;p&gt;I'm hoping that by throwing open development a bit, I can help showcase a bit about how I think and attack a new problem as a Haskell programmer.&lt;/p&gt;
&lt;p&gt;The latter parts are definitely currently unoptimized, but showcase what I think is a new technique (or at least a &quot;new to me&quot; technique) that I want to play with.&lt;/p&gt;
&lt;p&gt;With all that out of the way, lets move on to&lt;/p&gt;
&lt;h2 id=&quot;morton-ordering&quot;&gt;Morton Ordering&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Z-order_curve&quot;&gt;Morton ordering&lt;/a&gt; (aka the Z-curve) is a technique for getting cache locality in multiple dimensions by interleaving the bits of your different keys rather than storing them lexicographically. It was discovered way back in 1966, so I figured it was time to  write up an article about it.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/a3c0720604f7-Four-level_Z.svg&quot; alt=&quot;z-order&quot;&gt;&lt;/p&gt;
&lt;p&gt;The idea is that instead of picking one of the keys to put first you interleave their bits. Now, you are in some sense slightly screwed up when it comes to sorting by either axis, but you're more or less equally screwed no matter which way you go, and you're less screwed than you would be if you were cutting row-wise across a column-major or column-wise across a row-major ordered version of things. In general you get to exploit locality in either dimension to some degree. The extra locality you get isn't as good as you can get with a proper &lt;a href=&quot;http://en.wikipedia.org/wiki/Hilbert_curve&quot;&gt;Hilbert curve&lt;/a&gt; or with one of the other high end space filling curves, but those start requiring a lot more bit twiddling.&lt;/p&gt;
&lt;p&gt;(If someone wants to follow along the later parts with a Hilbert or H curve and find where my tricks fail, I'd love to see the result!)&lt;/p&gt;
&lt;p&gt;I want to work through how we can work with keys in Morton order in two ways. Today I'll walk through the first way.&lt;/p&gt;
&lt;p&gt;Neither of these techniques is particularly new, but having at least one of them is necessary for what is to come.&lt;/p&gt;
&lt;h2 id=&quot;every-day-i-m-shuffling&quot;&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=KQ6zr6kCPj8&amp;t=3m38s&quot;&gt;Every Day I'm Shuffling&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can turn to &lt;a href=&quot;http://www.hackersdelight.org/&quot;&gt;Hacker's Delight&lt;/a&gt; to find a routine for interleaving the high and low parts of a word together.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;c code&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;shuffle1&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;unsigned&lt;/span&gt; x)&lt;/span&gt; {
&lt;span class=&quot;hljs-comment&quot;&gt;// ------------------------------ cut ----------------------------------&lt;/span&gt;
   x = (x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF00&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; | (x &amp;gt;&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;) &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF00&lt;/span&gt; | x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FF&lt;/span&gt;;
   x = (x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F0&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; | (x &amp;gt;&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;) &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F0&lt;/span&gt; | x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00F&lt;/span&gt;;
   x = (x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; | (x &amp;gt;&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C&lt;/span&gt; | x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3&lt;/span&gt;;
   x = (x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x22222222&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; | (x &amp;gt;&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x22222222&lt;/span&gt; | x &amp;amp; &lt;span class=&quot;hljs-number&quot;&gt;0x99999999&lt;/span&gt;;
&lt;span class=&quot;hljs-comment&quot;&gt;// ---------------------------- end cut --------------------------------&lt;/span&gt;
   &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; x;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What this does is take a bunch of bits like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;abcd efgh ijkl mnop ABCD EFGH IJKL MNOP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then shuffles them until they are fully interleaved in parallel within the word carefully.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;abcd efgh ABCD EFGH ijkl mnop IJKL MNOP
abcd ABCD efgh EFGH ijkl IJKL mnop MNOP
abAB cdCD efEF ghGH ijIJ klKL mnMN opOP
aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can view this technique perhaps as an early precursor to something out of the more the modern SWAR (SIMD within a register) &lt;a href=&quot;http://aggregate.org/SWAR/Dis/dissertation.pdf&quot;&gt;toolbox&lt;/a&gt;, but we'll be doing everything by hand.&lt;/p&gt;
&lt;p&gt;Now, I want to work with slightly larger keys, and I'd rather work in Haskell, so we can transcode that and reimplement it to work on larger word sizes with appropriate tweaks to the constants involved.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Numeric.Lens


&lt;span class=&quot;hljs-title&quot;&gt;shuffle&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;shuffle&lt;/span&gt; k0 = k5 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k1 = unsafeShiftL (k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt; .|. k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
  k2 = unsafeShiftL (k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt; .|. k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
  k3 = unsafeShiftL (k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt; .|. k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
  k4 = unsafeShiftL (k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt; .|. k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
  k5 = unsafeShiftL (k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt; .|. k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- show main&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ base &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; # shuffle &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFFFFFF&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can build our &lt;code&gt;Key&lt;/code&gt; type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; i j = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; $ shuffle $ unsafeShiftL (fromIntegral i) &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt; .|. fromIntegral j
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/#morton-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For convenience, it'd be nice to see what the key was originally to show it, and later on to be able to project it back out, so first, lets define an &lt;code&gt;unshuffle&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Numeric.Lens


&lt;span class=&quot;hljs-title&quot;&gt;unshuffle&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;unshuffle&lt;/span&gt; k0 = k5 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  t0 = xor k0 (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;
  k1 = k0 `xor` t0 `xor` unsafeShiftL t0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  t1 = xor k1 (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;
  k2 = k1 `xor` t1 `xor` unsafeShiftL t1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  t2 = xor k2 (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;
  k3 = k2 `xor` t2 `xor` unsafeShiftL t2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
  t3 = xor k3 (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;
  k4 = k3 `xor` t3 `xor` unsafeShiftL t3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
  t4 = xor k4 (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;
  k5 = k4 `xor` t4 `xor` unsafeShiftL t4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE unshuffle #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- show main&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = print $ base &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; # unshuffle &lt;span class=&quot;hljs-number&quot;&gt;0xAAAAAAAAAAAAAAAA&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize Opportunity #1:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There exists an &lt;code&gt;unshuffle&lt;/code&gt; that works much more like &lt;code&gt;shuffle&lt;/code&gt;! What is the definition? The first reader to email me a working version of it wins a No-Prize.&lt;/p&gt;
&lt;p&gt;[&lt;strong&gt;Edit:&lt;/strong&gt; No-Prize #1 has been awarded to &lt;a href=&quot;https://twitter.com/SCombinator&quot;&gt;Sanjoy Das&lt;/a&gt;. However, &lt;a href=&quot;http://reddit.com/user/riotnerd&quot;&gt;riotnerd&lt;/a&gt; was the first to provide both a working unshuffle alongside the &lt;a href=&quot;http://www.reddit.com/r/haskell/comments/1kecqt/revisiting_matrix_multiplication_part_i_by_edward/cbo8qwy?context=3&quot;&gt;proof&lt;/a&gt; that they compose to identity and so he has earned an honorable mention. His presentation showed good style and demonstrated the equality via clean equational rewriting.]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unshuffle&lt;/span&gt; k0 = k5 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k5 = unsafeShiftL (k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt; .|. k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
  k4 = unsafeShiftL (k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt; .|. k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
  k3 = unsafeShiftL (k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt; .|. k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
  k2 = unsafeShiftL (k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt; .|. k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
  k1 = unsafeShiftL (k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt; .|. k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Interestingly, with &lt;code&gt;-fllvm&lt;/code&gt;, that change, and a high enough optimization level, GHC is smart enough to realize &lt;code&gt;shuffle . unshuffle = id&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;With that, we can implement&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unkey&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we have what we need to make an isomorphism.&lt;/p&gt;
&lt;p&gt;We could define&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;keyed&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Iso'&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;keyed&lt;/span&gt; = iso (uncurry key) unkey
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then we could expose field accessors that work like Key was a pair using the overloaded field accessors in &lt;code&gt;lens&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Field1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _1 = from keyed._1
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _2 = from keyed._2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this we can take a key, and freely manipulate one side of it with the lens combinators. e.g.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt; ^. _2 = &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt; &amp;amp; _2 .~ &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt; = key &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can use these to make a custom &lt;code&gt;Show&lt;/code&gt; and &lt;code&gt;Read&lt;/code&gt; for our &lt;code&gt;Key&lt;/code&gt; type that isn't so eyebleedingly tough to read:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  showsPrec d w = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; unkey w &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (i,j) -&amp;gt; showParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $
      showString &lt;span class=&quot;hljs-string&quot;&gt;&quot;key &quot;&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.showsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; i .
           showChar &lt;span class=&quot;hljs-string&quot;&gt;' '&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.showsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; j
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  readsPrec d = readParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $ \r -&amp;gt;
    [ (key i j, u)
    | (&lt;span class=&quot;hljs-string&quot;&gt;&quot;key&quot;&lt;/span&gt;,s) &amp;lt;- lex r
    , (i,t) &amp;lt;- readsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; s
    , (j,u) &amp;lt;- readsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; t
    ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;now most users don't need to care too much about the internal implementation of &lt;code&gt;Key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That said, we revisit our awesomely succinct implementation for &lt;code&gt;_1&lt;/code&gt; and &lt;code&gt;_2&lt;/code&gt; above, because we can implement &lt;code&gt;_1&lt;/code&gt; and &lt;code&gt;_2&lt;/code&gt; much more efficiently if we don't bother to shuffle and unshuffle the other side at all!&lt;/p&gt;
&lt;p&gt;Fortunately, once again the Hacker's Delight has our backs.&lt;/p&gt;
&lt;p&gt;This time I'm going to encode the indexed lens directly rather than compose it out of simpler pieces:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | Masks for the interleaved components of a key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m1&lt;/span&gt;, m2 :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m1&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0xAAAAAAAAAAAAAAAA&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- the mask for the first component of our key.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m2&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0x5555555555555555&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- the mask for the second component of our key.&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE m1 #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE m2 #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _2 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; ij) = indexed f (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) (fromIntegral k5) &amp;lt;&amp;amp;&amp;gt; \j -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
         j0 = fromIntegral j
         j1 = unsafeShiftL (j0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. j0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
         j2 = unsafeShiftL (j1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. j1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
         j3 = unsafeShiftL (j2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. j2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
         j4 = unsafeShiftL (j3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. j3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
         j5 = unsafeShiftL (j4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. j4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
      &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (ij .&amp;amp;. m1 .|. j5)
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      k0 = ij .&amp;amp;. m2
      k1 = (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. k0) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x3333333333333333&lt;/span&gt;
      k2 = (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. k1) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0F0F0F0F0F0F0F0F&lt;/span&gt;
      k3 = (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. k2) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00FF00FF00FF00FF&lt;/span&gt;
      k4 = (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. k3) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FFFF0000FFFF&lt;/span&gt;
      k5 = (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. k4) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFFFFFF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here _2 is being made manually into an 'indexed lens' (really just to make the Field typeclass happy), it is always index 1, and it half-unshuffles out the right hand side of my &lt;code&gt;Word64&lt;/code&gt; to make a Word32 suitable for consumption, and when given a replacement, shuffles it into place, and masks off what it is replacing in the &lt;code&gt;Key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I had a slightly fiddly issue with the signature that arose, because I needed to use a type equality rather than the more obvious &lt;code&gt;Field2 Key Key Word32 Word32&lt;/code&gt; instance to make it so that &lt;code&gt;(.~)&lt;/code&gt; selects the right instance.&lt;/p&gt;
&lt;p&gt;Exercise: Try changing it to the obvious version in the module at the bottom of this file and see what happens to main!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No-Prize opportunity #2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I'm currently using the following definition for &lt;code&gt;_1&lt;/code&gt;, but what does a cleaner version that avoids the shifts on &lt;code&gt;i5&lt;/code&gt; and &lt;code&gt;k0&lt;/code&gt; with modified masks/shifts look like? Email me first with the answer for your No-Prize.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _1 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; ij) = indexed f (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) (fromIntegral k5) &amp;lt;&amp;amp;&amp;gt; \i -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
         i0 = fromIntegral i
         i1 = unsafeShiftL (i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
         i2 = unsafeShiftL (i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
         i3 = unsafeShiftL (i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
         i4 = unsafeShiftL (i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
         i5 = unsafeShiftL (i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
      &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (unsafeShiftL i5 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; .|. ij .&amp;amp;. m2)
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      k0 = unsafeShiftR (ij .&amp;amp;. m1) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
      k1 = (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. k0) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x3333333333333333&lt;/span&gt;
      k2 = (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. k1) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0F0F0F0F0F0F0F0F&lt;/span&gt;
      k3 = (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. k2) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00FF00FF00FF00FF&lt;/span&gt;
      k4 = (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. k3) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FFFF0000FFFF&lt;/span&gt;
      k5 = (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. k4) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFFFFFF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[ Edit: No-Prize #2 is has been (partially!) awarded to &lt;a href=&quot;http://www.thenewsh.com/~newsham/&quot;&gt;Tim Newsham&lt;/a&gt;, who provided the solution by carefully working the shifts back through the masks after he was stymied in his quest for No-Prize #1 by being too late to the party. His solution resolves the shifts on &lt;code&gt;k5&lt;/code&gt;, but not &lt;code&gt;i0&lt;/code&gt;. Can we do better? Why or why not? I also realize that in practice the reduction in constant sharing may likely outweigh the removal of the shift.]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _1 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; ij) = indexed f (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) (fromIntegral k5) &amp;lt;&amp;amp;&amp;gt; \i -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
         i0 = fromIntegral i
         i1 = unsafeShiftL (i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;17&lt;/span&gt; .|. i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFE00000001FFFE&lt;/span&gt;
         i2 = unsafeShiftL (i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;  .|. i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFE0001FFFE0001FE&lt;/span&gt;
         i3 = unsafeShiftL (i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;  .|. i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xE01FE01FE01FE01E&lt;/span&gt;
         i4 = unsafeShiftL (i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;  .|. i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0F0F0F0F0F0F0F0E&lt;/span&gt;
         i5 = unsafeShiftL (i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x3333333333333332&lt;/span&gt;
      &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (unsafeShiftL &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; i5 .|. ij .&amp;amp;. m2)
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      k0 = ij .&amp;amp;. m1
      k1 = (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. k0) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x6666666666666666&lt;/span&gt;
      k2 = (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;  .|. k1) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x1E1E1E1E1E1E1E1E&lt;/span&gt;
      k3 = (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;  .|. k2) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x01FE01FE01FE01FE&lt;/span&gt;
      k4 = (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;  .|. k3) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0001FFFE0001FFFE&lt;/span&gt;
      k5 = (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt; .|. k4) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000001FFFFFFFE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The current implementation of this code, with whatever changes have been made in the meantime, sans some cleanup for presentation is currently available as &lt;a href=&quot;https://github.com/ekmett/sparse/blob/master/src/Sparse/Matrix/Key.hs&quot;&gt;Sparse/Matrix/Key.hs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now we can compare two keys for Morton order just by embedding them and comparing them, but can we do better?&lt;/p&gt;
&lt;h2 id=&quot;a-strange-game&quot;&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=uOoXwxqeVzg&quot;&gt;A Strange Game&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I'll pick up next time with how we can compare two keys by their Morton ordering without actually performing the interleaving at all! This technique will be important in what is to come, even if we may not use it directly for the keys themselves.&lt;/p&gt;
&lt;p&gt;Hopefully by parts 3 or 4 we'll be deep in the bowels of Vector carving up custom stream fusion combinators and rethinking whether we want to partition a matrix or &quot;thin&quot; it to build an efficient sparse matrix multiplication routine.&lt;/p&gt;
&lt;p&gt;I've included a current copy of the &lt;code&gt;Key&lt;/code&gt; code below as an active document with minor alterations to enable you to play with it interactively. (It has a few cosmetic differences from the code above.)&lt;/p&gt;
&lt;p&gt;-&lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;
August 14th, 2013&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- show Sparse/Matrix/Key.hs&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE KindSignatures #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DefaultSignatures #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleContexts #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-----------------------------------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- |&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Copyright   :  (C) 2013 Edward Kmett&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- License     :  BSD-style (see the file LICENSE)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Maintainer  :  Edward Kmett &amp;lt;ekmett@gmail.com&amp;gt;&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Stability   :  experimental&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Portability :  non-portable&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Keys in Morton order&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- This module provides combinators for shuffling together the bits of two&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- key components to get a key that is based on their interleaved bits.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- See &amp;lt;http://en.wikipedia.org/wiki/Z-order_curve&amp;gt; for more information&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- about Morton order.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;----------------------------------------------------------------------------&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Morton Order&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | @key i j@ interleaves the bits of the keys @i@ and @j@.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- Keys are then just values sorted in \&quot;Morton Order\&quot;.&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runKey&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt; }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Construct a key from a pair of indices.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- key i j ^. _1 = i&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- key i j ^. _2 = j&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;key&lt;/span&gt; i j = &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; k5 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  k0 = unsafeShiftL (fromIntegral i) &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt; .|. fromIntegral j
  k1 = unsafeShiftL (k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt; .|. k0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
  k2 = unsafeShiftL (k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt; .|. k1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
  k3 = unsafeShiftL (k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt; .|. k2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
  k4 = unsafeShiftL (k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt; .|. k3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
  k5 = unsafeShiftL (k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt; .|. k4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE key #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | This isomorphism lets you build a key from a pair of indices.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- key i j ≡ (i,j)^.shuffled&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- 'shuffled' . 'unshuffled' = 'id'&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- 'unshuffled' . 'shuffled' = 'id'&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- @&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;shuffled&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Iso'&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;shuffled&lt;/span&gt; = iso (uncurry key) unshuffle
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE shuffled #-}&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | This isomorphism lets you build a pair of indices from a key.&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;unshuffled&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Iso'&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;unshuffled&lt;/span&gt; = iso unshuffle (uncurry key)
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE unshuffled #-}&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;unshuffle&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;unshuffle&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; k0) = (fromIntegral (unsafeShiftR k5 &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;), fromIntegral k5) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  t0 = xor k0 (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;
  k1 = k0 `xor` t0 `xor` unsafeShiftL t0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  t1 = xor k1 (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;
  k2 = k1 `xor` t1 `xor` unsafeShiftL t1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
  t2 = xor k2 (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;
  k3 = k2 `xor` t2 `xor` unsafeShiftL t2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
  t3 = xor k3 (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;
  k4 = k3 `xor` t3 `xor` unsafeShiftL t3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;
  t4 = xor k4 (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;
  k5 = k4 `xor` t4 `xor` unsafeShiftL t4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE unshuffle #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field1&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _1 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; ij) = indexed f (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) (fromIntegral k5) &amp;lt;&amp;amp;&amp;gt; \i -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
         i0 = fromIntegral i
         i1 = unsafeShiftL (i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. i0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
         i2 = unsafeShiftL (i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. i1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
         i3 = unsafeShiftL (i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. i2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
         i4 = unsafeShiftL (i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. i3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
         i5 = unsafeShiftL (i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. i4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
      &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (unsafeShiftL i5 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; .|. ij .&amp;amp;. m2)
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      k0 = unsafeShiftR (ij .&amp;amp;. m1) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
      k1 = (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. k0) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x3333333333333333&lt;/span&gt;
      k2 = (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. k1) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0F0F0F0F0F0F0F0F&lt;/span&gt;
      k3 = (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. k2) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00FF00FF00FF00FF&lt;/span&gt;
      k4 = (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. k3) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FFFF0000FFFF&lt;/span&gt;
      k5 = (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. k4) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFFFFFF&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- _1 = unshuffled._1 -- reference implementation&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE _1 #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; ~ &lt;span class=&quot;hljs-type&quot;&gt;Word32&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Field2&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; a b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _2 f (&lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; ij) = indexed f (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) (fromIntegral k5) &amp;lt;&amp;amp;&amp;gt; \j -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
         j0 = fromIntegral j
         j1 = unsafeShiftL (j0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFF0000&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. j0 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFFFF00000000FFFF&lt;/span&gt;
         j2 = unsafeShiftL (j1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FF000000FF00&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. j1 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xFF0000FFFF0000FF&lt;/span&gt;
         j3 = unsafeShiftL (j2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00F000F000F000F0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. j2 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xF00FF00FF00FF00F&lt;/span&gt;
         j4 = unsafeShiftL (j3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0C0C0C0C0C0C0C0C&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. j3 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0xC3C3C3C3C3C3C3C3&lt;/span&gt;
         j5 = unsafeShiftL (j4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x2222222222222222&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. j4 .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x9999999999999999&lt;/span&gt;
      &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; (ij .&amp;amp;. m1 .|. j5)
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      k0 = ij .&amp;amp;. m2
      k1 = (unsafeShiftR k0 &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;  .|. k0) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x3333333333333333&lt;/span&gt;
      k2 = (unsafeShiftR k1 &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;  .|. k1) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0F0F0F0F0F0F0F0F&lt;/span&gt;
      k3 = (unsafeShiftR k2 &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;  .|. k2) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00FF00FF00FF00FF&lt;/span&gt;
      k4 = (unsafeShiftR k3 &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;  .|. k3) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x0000FFFF0000FFFF&lt;/span&gt;
      k5 = (unsafeShiftR k4 &lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt; .|. k4) .&amp;amp;. &lt;span class=&quot;hljs-number&quot;&gt;0x00000000FFFFFFFF&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- _2 = unshuffled._2 -- reference implementation&lt;/span&gt;
  &lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE _2 #-}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  showsPrec d w = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; unshuffle w &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (i,j) -&amp;gt; showParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $
      showString &lt;span class=&quot;hljs-string&quot;&gt;&quot;key &quot;&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.showsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; i .
           showChar &lt;span class=&quot;hljs-string&quot;&gt;' '&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Prelude&lt;/span&gt;.showsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; j
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  readsPrec d = readParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $ \r -&amp;gt;
    [ (key i j, u)
    | (&lt;span class=&quot;hljs-string&quot;&gt;&quot;key&quot;&lt;/span&gt;,s) &amp;lt;- lex r
    , (i,t) &amp;lt;- readsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; s
    , (j,u) &amp;lt;- readsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; t
    ]

&lt;span class=&quot;hljs-comment&quot;&gt;-- * Utilities&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Masks for the interleaved components of a key&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m1&lt;/span&gt;, m2 :: &lt;span class=&quot;hljs-type&quot;&gt;Word64&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m1&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0xAAAAAAAAAAAAAAAA&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;m2&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0x5555555555555555&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE m1 #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# INLINE m2 #-}&lt;/span&gt;


&lt;span class=&quot;hljs-comment&quot;&gt;-- show playground&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
 print $ key &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt; ^. _2
 print $ key &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;200&lt;/span&gt; &amp;amp; _1 .~ &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/revisiting-matrix-multiplication-part-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cellular Automata — Part I: From Theory to Pretty Pictures</title><link>https://comonad.com/reader/2014/cellular-automata-part-1/</link><guid isPermaLink="false">https://comonad.com/reader/2014/cellular-automata-part-1/</guid><pubDate>Thu, 15 Aug 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 August 2013&lt;/p&gt;&lt;p&gt;Cellular automata are one of the &quot;go to&quot; examples for comonads in Haskell.&lt;/p&gt;
&lt;p&gt;Dan Piponi wrote his article on &lt;a href=&quot;http://blog.sigfpe.com/2006/12/evaluating-cellular-automata-is.html&quot;&gt;using comonads to evaluate cellular automata&lt;/a&gt; back in 2006, and that was pretty much my introduction to comonads in general. He used a &lt;a href=&quot;http://en.wikipedia.org/wiki/Zipper_%28data_structure%29&quot;&gt;list zipper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Today, I want to use something a little bit more general and maybe draw some pictures.&lt;/p&gt;
&lt;h2 id=&quot;minding-the-store&quot;&gt;Minding The Store&lt;/h2&gt;
&lt;p&gt;To that end, let's define the &lt;code&gt;Store&lt;/code&gt; &lt;code&gt;Comonad&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad


&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f) s

&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f &amp;lt;$&amp;gt; k s

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, so it must be correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;Store s a&lt;/code&gt; describes some &quot;test&quot; that takes a configuration &lt;code&gt;s&lt;/code&gt; and will produce a value of type &lt;code&gt;a&lt;/code&gt;, where we also have some ambient initial configuration of type &lt;code&gt;s&lt;/code&gt; that is known with which we could start the experiment.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;experiment&lt;/code&gt; combinator characterizes a &lt;code&gt;Store&lt;/code&gt; completely. It lets you explore variations on the initial conditions of our test.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f &amp;lt;$&amp;gt; k s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Store&lt;/code&gt; gives you a little bit more power than we want in a cellular automaton, as you can do both relative &lt;em&gt;and&lt;/em&gt; global addressing, but it happens to be a very general construction, so we'll start there. It has the benefit that if we decide we want to play with automata in more than 1 dimension all we have to do is change out the state type.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Store&lt;/code&gt; comonad has a lot of different uses that aren't immediately obvious. It is used heavily inside of the &lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;
&lt;h2 id=&quot;a-glimpse-down-the-rabbit-hole&quot;&gt;A Glimpse Down the Rabbit Hole&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(This section is completely skippable and is included as a highly technical aside)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;An interesting exercise for the advanced Haskeller is to flip the definition of &lt;code&gt;experiment&lt;/code&gt; and take that as the definition for &lt;code&gt;Store&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Pretext&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Pretext&lt;/span&gt; {
    &lt;span class=&quot;hljs-title&quot;&gt;runPretext&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;. &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;
  } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pretext&lt;/span&gt; s a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Pretext&lt;/span&gt; k) = k f

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, so it must be correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Defining the &lt;code&gt;Comonad&lt;/code&gt; instance for that type is a particularly enlightening challenge.&lt;/p&gt;
&lt;p&gt;If you replace the &lt;code&gt;Functor&lt;/code&gt; constraint in the definition above with &lt;code&gt;Applicative&lt;/code&gt; you get a &lt;code&gt;Comonad&lt;/code&gt; I call the &lt;code&gt;Bazaar&lt;/code&gt;. This &lt;code&gt;Comonad&lt;/code&gt; is used to derive many of the most brain-bending &lt;code&gt;Traversal&lt;/code&gt; and &lt;code&gt;uniplate&lt;/code&gt;-derived combinators in &lt;code&gt;lens&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The code for its &lt;code&gt;Comonad&lt;/code&gt; instance is identical to the instance for &lt;code&gt;Pretext&lt;/code&gt; above, but it can also be made &lt;code&gt;Applicative&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Bazaar&lt;/span&gt; {
    &lt;span class=&quot;hljs-title&quot;&gt;runBazaar&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;. &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; =&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;
  } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, so it must be correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you try to search for the &lt;code&gt;Store&lt;/code&gt;-like analogue to the &lt;code&gt;Bazaar&lt;/code&gt;, you wind up looking at what Twan van Laarhoven called a &lt;code&gt;FunList&lt;/code&gt; in &lt;a href=&quot;http://twanvl.nl/blog/haskell/non-regular1&quot;&gt;&quot;A non-regular data type challenge&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FunList&lt;/span&gt; s a&lt;/span&gt;
    = &lt;span class=&quot;hljs-type&quot;&gt;Done&lt;/span&gt; a
    | &lt;span class=&quot;hljs-type&quot;&gt;More&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;FunList&lt;/span&gt; s (s -&amp;gt; a))
    &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;It typechecks, so it must be correct!&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An interesting exercise is to derive the &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;Comonad&lt;/code&gt; instances for &lt;code&gt;FunList&lt;/code&gt;. This exercise is much easier than the &lt;code&gt;Pretext&lt;/code&gt; and &lt;code&gt;Bazaar&lt;/code&gt; derivations, but still quite challenging.&lt;/p&gt;
&lt;p&gt;Surprisingly &lt;code&gt;FunList&lt;/code&gt; is actually a less powerful type than &lt;code&gt;Bazaar&lt;/code&gt; in the presence of infinite traversals as many tools you can build will not terminate when you manipulate an infinite traversal with them built using a &lt;code&gt;FunList&lt;/code&gt;, but &lt;em&gt;will&lt;/em&gt; terminate when they are constructed using the &lt;code&gt;Bazaar&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&quot;following-the-rules&quot;&gt;Following the Rules&lt;/h2&gt;
&lt;p&gt;Stephen Wolfram described a rather concise encoding of 2-color automata that can only look at their neighbors in &lt;a href=&quot;http://www.wolframscience.com/&quot;&gt;&quot;A New Kind of Science&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can encode his family of 2-color rules as a comonadic action:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = testBit w $
  &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;amp; partsOf (taking &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; bits) .~ [f (s+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), f s, f (s-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is rather dense, so let's unpack it.&lt;/p&gt;
&lt;p&gt;Wolfram numbers his rules from 0 to 255 because if you look at the current cell and the neighbor to the left and right of it, we have 3 inputs to consider. Each is a &lt;code&gt;Bool&lt;/code&gt; so we have &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; different results to give. If we bundle all those possible results together as the bits of a &lt;code&gt;Word8&lt;/code&gt;, the &lt;code&gt;Word8&lt;/code&gt; perfectly describes all of the possible 2-color cellular automata that can look at the current and neighboring cells.&lt;/p&gt;
&lt;p&gt;So now the trick is doing that indexing. To do so, first we need to figure out which bit in our &lt;code&gt;Word8&lt;/code&gt; we are interested in. To do that we need to use the 3 booleans we obtain by tweaking our position and asking to perform our &quot;experiment&quot; there at the slightly modified positions instead.&lt;/p&gt;
&lt;p&gt;Now we want to compose 3 bits together into an &lt;code&gt;Int&lt;/code&gt;. We could do this with a bunch of conditional logic, etc. but there is a slightly cute encoding we can get when we use &lt;code&gt;lens&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bits&lt;/code&gt; provides a &lt;code&gt;Traversal&lt;/code&gt; of the individual bits of any instance of &lt;code&gt;Bits&lt;/code&gt;. (In the case of &lt;code&gt;Integer&lt;/code&gt;, though, because it is infinite sadly the &lt;code&gt;Traversal&lt;/code&gt; can never finish reassembling the &lt;code&gt;Integer&lt;/code&gt;, and so it devolves to merely a &lt;code&gt;Fold&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;taking n t&lt;/code&gt; takes a &lt;code&gt;Traversal t&lt;/code&gt; and yields a &lt;code&gt;Traversal&lt;/code&gt; that only touches the first &lt;code&gt;n&lt;/code&gt; targets of the original &lt;code&gt;Traversal&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Therefore &lt;code&gt;taking 3 bits&lt;/code&gt; is the &lt;code&gt;Traversal&lt;/code&gt; of the first 3 bits of a number.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;partsOf&lt;/code&gt; takes a &lt;code&gt;Traversal&lt;/code&gt; and gives you a (slightly hinky) &lt;code&gt;Lens&lt;/code&gt; to a list of all of the targets of the traversal. You can freely replace that list with a new list (of the same length!). It is only a law abiding &lt;code&gt;Lens&lt;/code&gt; if you do not change the length of the list of targets, but even if you violate these assumptions it is well behaved operationally. In fact you can safely remove &lt;code&gt;taking n&lt;/code&gt; from the definition of rule above, and its semantics do not change.&lt;/p&gt;
&lt;p&gt;And finally, we can use the fact that every &lt;code&gt;Lens&lt;/code&gt; is a valid &lt;code&gt;Setter&lt;/code&gt; to make the assignment.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;amp; partsOf (taking &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; bits) .~ [f (s+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), f s, f (s-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then builds an &lt;code&gt;Int&lt;/code&gt; &lt;em&gt;n&lt;/em&gt; between 0 and 7 by starting with a 0 and setting its first 3 bits accordingly.&lt;/p&gt;
&lt;p&gt;With that in hand we can now test the _n_th bit of the rule number and obtain our result.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;Store s&lt;/code&gt; forms a &lt;code&gt;Comonad&lt;/code&gt; though, we can &lt;code&gt;extend&lt;/code&gt; our &lt;code&gt;rule n&lt;/code&gt; to obtain a new &lt;code&gt;Store s Bool&lt;/code&gt; from our existing &lt;code&gt;Store s Bool&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now if we, say, &lt;code&gt;extend (rule 110)&lt;/code&gt; we get a function from one world to a new world, where that
rule has been applied uniformly across the entire world at the same time.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;extend&lt;/span&gt; (rule &lt;span class=&quot;hljs-number&quot;&gt;110&lt;/span&gt;) :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By choosing an appropriate number type for &lt;code&gt;s&lt;/code&gt; we can choose the topology for our automaton to live on!&lt;/p&gt;
&lt;p&gt;We could repeatedly run our rules with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;slowLoop&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a]
&lt;span class=&quot;hljs-title&quot;&gt;slowLoop&lt;/span&gt; f = iterate (extend f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/cellular-automata-part-1/#automaton-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;got-the-memo&quot;&gt;Got the Memo?&lt;/h2&gt;
&lt;p&gt;...but we'd get explosive slowdown. Why?&lt;/p&gt;
&lt;p&gt;After each loop iteration we depend on 3x as many evaluations as we did for the iteration before, because each evaluation is asking for all of the other old versions of the old neighbors, etc.&lt;/p&gt;
&lt;p&gt;So the trick is to memoize our function. The easiest way to do that without reasoning about &lt;code&gt;IO&lt;/code&gt; is to use a memo combinator package like &lt;code&gt;data-memocombinators&lt;/code&gt; or my own &lt;code&gt;representable-tries&lt;/code&gt;. I'll buck my trend and use Luke's package instead of mine.&lt;/p&gt;
&lt;p&gt;But which function?&lt;/p&gt;
&lt;p&gt;We don't want to memoize the comonad algebra itself. The argument to that is of type &lt;code&gt;Store s a&lt;/code&gt;, and memoizing function spaces of function spaces gets truly messy. Let's make a function that turns a value in our &lt;code&gt;Store&lt;/code&gt; comonad into one that memoizes its answers by memoizing the experiment it contains.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Memo&lt;/span&gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; opt (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (opt f) s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;tab&lt;/code&gt; takes a way to memoize a function from the context of our &lt;code&gt;Store&lt;/code&gt; and a &lt;code&gt;Store&lt;/code&gt; and yields a new &lt;code&gt;Store&lt;/code&gt; that memoizes its results.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Memo&lt;/code&gt; comes from &lt;code&gt;data-memocombinators&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Memo&lt;/span&gt; a = forall r. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; a -&amp;gt; r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A value of type &lt;code&gt;Memo a&lt;/code&gt; describes a memoization strategy for functions from values of type &lt;code&gt;a&lt;/code&gt;. It takes a function and turns it into a function that memoizes its results. It does so in a completely pure way that is worth exploring in its own right, but...&lt;/p&gt;
&lt;p&gt;If we just use the fact that &lt;code&gt;integral&lt;/code&gt; provides us with such a memoization strategy that works for any &lt;code&gt;Integral&lt;/code&gt; type, we can derive a smarter &lt;code&gt;loop&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; s =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a]
&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (extend f . tab integral)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here when we are given a new &lt;code&gt;Store&lt;/code&gt; before each iteration we simply upgrade it to memoize its results for each position as it is asked before handing it to our rule for further evaluation.&lt;/p&gt;
&lt;h2 id=&quot;let-s-do-the-time-warp-again&quot;&gt;Let's Do the Time Warp Again&lt;/h2&gt;
&lt;p&gt;Now let's timewarp back to the stone age and print out endless reams of paper filled with automaton states.&lt;/p&gt;
&lt;p&gt;To do that we need a way to see what some slice of our world looks like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- &lt;span class=&quot;hljs-doctag&quot;&gt;TODO:&lt;/span&gt; copy the whole program below here&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Strict
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.MemoCombinators
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Diagrams.Backend.SVG
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Diagrams.Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; D
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Blaze.Svg.Renderer.Utf8
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f) s

&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f &amp;lt;$&amp;gt; k s

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = testBit w $
  &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf (taking &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits) .~ [f (s+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), f s, f (s-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]

&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Memo&lt;/span&gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; opt (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (opt f) s

&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; s =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a]
&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (extend f . tab integral)


&lt;span class=&quot;hljs-title&quot;&gt;window&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; s, &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s) =&amp;gt; s -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [a]
&lt;span class=&quot;hljs-title&quot;&gt;window&lt;/span&gt; l h = experiment $ \ s -&amp;gt; [s-l..s+h]

&lt;span class=&quot;hljs-title&quot;&gt;xo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xo&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;  = &lt;span class=&quot;hljs-string&quot;&gt;'X'&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;xo&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;' '&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = mapM_ (putStrLn . map xo . window &lt;span class=&quot;hljs-number&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) $
       take &lt;span class=&quot;hljs-number&quot;&gt;50&lt;/span&gt; $ loop (rule &lt;span class=&quot;hljs-number&quot;&gt;110&lt;/span&gt;) $ &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (==&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I probably should have told that thing stop printing a little sooner. Sorry. ;)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;window&lt;/code&gt; varies our position on the number line up or down a bit so we can see several data points.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xo&lt;/code&gt; converts each result into a form we might want to see.&lt;/p&gt;
&lt;p&gt;Then we put it all together and run Wolfram's &lt;a href=&quot;http://en.wikipedia.org/wiki/Rule_110&quot;&gt;rule 110&lt;/a&gt; starting with a single point at position 0 as our initial condition.&lt;/p&gt;
&lt;h2 id=&quot;pretty-as-a-picture&quot;&gt;Pretty as a Picture&lt;/h2&gt;
&lt;p&gt;It isn't the stone age any more.&lt;/p&gt;
&lt;p&gt;Matt Sottile did a pretty looking &lt;a href=&quot;http://syntacticsalt.com/2010/08/30/forest-fire-cellular-automaton-haskell-and-matlab/&quot;&gt;forest fire&lt;/a&gt; cellular automata example a couple of years back. But he had to render everything by hand using OpenGL.&lt;/p&gt;
&lt;p&gt;Nowadays we can draw pretty pictures using Brent Yorgey's awesome &lt;code&gt;diagrams&lt;/code&gt; package rather than carve ASCII &lt;code&gt;X&lt;/code&gt;'s into the walls of our cave.&lt;/p&gt;
&lt;p&gt;Now that we have the windows of data we want, all we need to do is turn each &lt;code&gt;window&lt;/code&gt; into a a bunch of squares and stitch those rows together into a &lt;code&gt;Diagram&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;grid&lt;/span&gt; :: [[&lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;]] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Diagram&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;grid&lt;/span&gt; = vcat . map (hcat . cell) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  cell b = unitSquare &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;.# fc (&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; black &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; white)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This post was spawned from a discussion with Rein Henrichs on #haskell. He supplied the initial version of the &lt;code&gt;diagrams&lt;/code&gt; code. His version was much prettier.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;diagrams&lt;/code&gt; supports rendering to a ton of formats including SVG, so we can transform our diagram into a document using &lt;code&gt;diagrams-svg&lt;/code&gt; and &lt;code&gt;blaze-svg&lt;/code&gt;. We could also render it directly to &lt;code&gt;cairo&lt;/code&gt; and get out a PNG, get out an HTML canvas, a postscript document, etc.&lt;/p&gt;
&lt;p&gt;We could use the &lt;code&gt;renderSVG&lt;/code&gt; function to generate a file on disk, but it also isn't the 80s. Command line tools that spit out files are passé. So lets just get our hands on the file here in memory as a &lt;code&gt;ByteString&lt;/code&gt; and make sure it's strict to deal with the impedence mismatch between the tools I'm using.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;svg&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Diagram&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R2&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Strict&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;svg&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Strict&lt;/span&gt;.concat . &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.toChunks .
      renderSvg . renderDia &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;SVGOptions&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Width&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;400&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;but-is-it-web-scale&quot;&gt;But is it Web Scale?&lt;/h2&gt;
&lt;p&gt;The School of Haskell supports &lt;a href=&quot;https://www.fpcomplete.com/blog/2013/08/snap-happstack-anything-else&quot;&gt;running&lt;/a&gt; full-fledged web-based applications from an &quot;active&quot; Haskell snippet, so lets give it a try.&lt;/p&gt;
&lt;p&gt;If we put them these pieces of code together you should be able to click run below and get out pretty pictures out of a custom web server that all but fits on your screen.&lt;/p&gt;
&lt;p&gt;Click Run!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeFamilies #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE QuasiQuotes #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE MultiParamTypeClasses #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE DeriveFunctor #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Bits.Lens &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; L
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Strict
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.ByteString.Lazy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Lazy
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.MemoCombinators
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Word
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Diagrams.Backend.SVG
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Diagrams.Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; D
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Blaze.Svg.Renderer.Utf8
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Yesod

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) s &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f s
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f) s

&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (s -&amp;gt; f s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;experiment&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = f &amp;lt;$&amp;gt; k s

&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Word8&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = testBit w $ &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.&amp;amp; partsOf (taking &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt;.bits) .~ [f (s+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), f s, f (s-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]

&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Memo&lt;/span&gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;tab&lt;/span&gt; opt (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; f s) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (opt f) s

&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; s =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a]
&lt;span class=&quot;hljs-title&quot;&gt;loop&lt;/span&gt; f = iterate (extend f . tab integral)

&lt;span class=&quot;hljs-title&quot;&gt;window&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; s, &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; s) =&amp;gt; s -&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s a -&amp;gt; [a]
&lt;span class=&quot;hljs-title&quot;&gt;window&lt;/span&gt; l h = experiment $ \ s -&amp;gt; [s-l..s+h]

&lt;span class=&quot;hljs-title&quot;&gt;grid&lt;/span&gt; :: [[&lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;]] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Diagram&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R2&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;grid&lt;/span&gt; = cat unitY . reverse . map (hcat . map cell) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  cell b = unitSquare &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;.# fc (&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; black &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; white)

&lt;span class=&quot;hljs-title&quot;&gt;svg&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Diagram&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;R2&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Strict&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ByteString&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;svg&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Strict&lt;/span&gt;.concat . &lt;span class=&quot;hljs-type&quot;&gt;Lazy&lt;/span&gt;.toChunks . renderSvg . renderDia &lt;span class=&quot;hljs-type&quot;&gt;SVG&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;SVGOptions&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Width&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;400&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yesod&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;

mkYesod &quot;&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;&quot; [parseRoutes| / &lt;span class=&quot;hljs-type&quot;&gt;ImageR&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GET&lt;/span&gt; |]

getImageR :: &lt;span class=&quot;hljs-type&quot;&gt;MonadHandler&lt;/span&gt; m =&amp;gt; m &lt;span class=&quot;hljs-type&quot;&gt;TypedContent&lt;/span&gt;
getImageR = sendResponse $ toTypedContent (&lt;span class=&quot;hljs-title&quot;&gt;typeSvg&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;toContent&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;img&lt;/span&gt;)

img = svg . grid . map (&lt;span class=&quot;hljs-title&quot;&gt;window&lt;/span&gt; 49 0) . take 50 . loop (&lt;span class=&quot;hljs-title&quot;&gt;rule&lt;/span&gt; 110) $ &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (==0) (0 :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)

main = warpEnv &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That clocks in at 60 lines of code. In that much space we defined the &lt;code&gt;Store&lt;/code&gt; comonad, defined a generic evaluator that can handle any of Wolfram's 2-color automata, built a system of memoization to avoid asymptotic slowdown, took a cross section of our universe, and then rendered it to a diagram and built a custom web server to display that content here on the internet.&lt;/p&gt;
&lt;p&gt;Almost all of the components we built are generic. We can define new types of automata, try out new initial conditions, jump around in time, with some work we can support multiple colors, new topologies, render the same diagram to different file formats conditionally based on browser preferences. The code above can be edited live here in your browser or downloaded and run locally on your own machine.&lt;/p&gt;
&lt;p&gt;In the interest of full disclosure, the SVG that is rendered is far from optimal. The &lt;code&gt;diagrams&lt;/code&gt; crew is aware of the issue and they are hard at work improving the way &lt;code&gt;diagrams&lt;/code&gt; streams primitives to its backends, allowing it to take advantage of all the glorious structure that they have inside the &lt;code&gt;Diagram&lt;/code&gt; type described in Brent's &lt;a href=&quot;http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf&quot;&gt;excellent functional pearl&lt;/a&gt;. Currently the communication process between &lt;code&gt;diagrams&lt;/code&gt; and the backend is duplicating the transformation matrix and styling on a per element basis, and this is resulting in a much inflated document. When those changes go into &lt;code&gt;diagrams&lt;/code&gt; and &lt;code&gt;diagrams-svg&lt;/code&gt;, then this example will become &lt;em&gt;much&lt;/em&gt; faster with no changes to this code.&lt;/p&gt;
&lt;p&gt;I hope this shows how you can use a little bit of theory and some of the more practical components of the Haskell ecosystem to accomplish a lot with very little code.&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;Edward Kmett&lt;/a&gt;
August 15, 2013&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2014/cellular-automata-part-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Representing Applicatives</title><link>https://comonad.com/reader/2013/representing-applicatives/</link><guid isPermaLink="false">https://comonad.com/reader/2013/representing-applicatives/</guid><pubDate>Thu, 02 May 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 2 May 2013&lt;/p&gt;&lt;p&gt;In the &lt;a href=&quot;https://comonad.com/reader/2012/abstracting-with-applicatives/&quot;&gt;previous&lt;/a&gt; &lt;a href=&quot;https://comonad.com/reader/2013/algebras-of-applicatives/&quot;&gt;two&lt;/a&gt; posts, we've built up a whole range of applicatives, out of Const, Identity, Reader, Compose, Product, Sum, and Fix (and some higher-order analogues). Sum has given us the most trouble, but in some sense has been the most powerful, letting us write things like possibly eventually terminating lists, or trees, or in fact any sort of structure with branching alternatives. In this post, I want to think a bit more about why it is that Sum is the trickiest of the bunch, and more generally, what we can say about when two applicative structures are the &quot;same&quot;. In the process of doing so, we'll invent something a lot like Traversable en passant.&lt;/p&gt;
&lt;p&gt;Let's do some counting exercises. &lt;code&gt;Product Identity Identity&lt;/code&gt; holds exactly two things. It is therefore isomorphic to &lt;code&gt;((-&amp;gt;) Bool)&lt;/code&gt;, or if we prefer, &lt;code&gt;((-&amp;gt;) Either () ())&lt;/code&gt;. That is to say that a pair that &lt;em&gt;holds&lt;/em&gt; two values of type &lt;code&gt;a&lt;/code&gt; is the same as a function that &lt;em&gt;takes a two-valued type&lt;/em&gt; and &lt;em&gt;yields&lt;/em&gt; a value of type &lt;code&gt;a&lt;/code&gt;. A product of more functors in turn is isomorphic to the reader of the sum of each of the datatypes that &quot;represent&quot; them. E.g. &lt;code&gt;Product (Product Identity Identity) (Product (Const ()) Identity)&lt;/code&gt; is iso to &lt;code&gt;((-&amp;gt;) (Either (Either () ()) ())&lt;/code&gt;, i.e. a data type with three possible inhabitants. In making this move we took Product to Either -- multiplication to sum. We can pull a similar trick with Compose. &lt;code&gt;Compose (Product Identity Identity) (Product Identity Identity)&lt;/code&gt; goes to ((-&amp;gt;) (Either () (),Either () ())). So again we took Product to a sum type, but now we took Compose to a pair -- a product type! The intuition is that composition &lt;em&gt;multiplies&lt;/em&gt; the possibilities of spaces in each nested functor.&lt;/p&gt;
&lt;p&gt;Hmm.. products go to sums, composition goes to multiplication, etc. This should remind us of something -- these rules are exactly the rules for working with exponentials. x^n * x^m = x^(n + m). (x^n)^m = x^(n*m). x^0 = 1, x^1 = x.&lt;/p&gt;
&lt;p&gt;Seen from the right standpoint, this isn't surprising at all, but almost inevitable. The functors we're describing are known as &quot;representable,&quot; a term which derives from category theory. (See appendix on representable functors below).&lt;/p&gt;
&lt;p&gt;In Haskell-land, a &quot;representable functor&quot; is just any functor isomorphic to the reader functor &lt;code&gt;((-&amp;gt;) a)&lt;/code&gt; for some appropriate a. Now if we think back to our algebraic representations of data types, we call the arrow type constructor an exponential. We can &quot;count&quot; &lt;code&gt;a -&amp;gt; x&lt;/code&gt; as x^a, since e.g. there are 3^2 distinct functions that inhabit the type 2 -&amp;gt; 3. The intuition for this is that for each input we pick one of the possible results, so as the number of inputs goes up by one, the number of functions goes up by multiplying through by the set of possible results. 1 -&amp;gt; 3 = 3, 2 -&amp;gt; 3 = 3 * 3, (n + 1) -&amp;gt; 3 = 3 * (n -&amp;gt; 3).&lt;/p&gt;
&lt;p&gt;Hence, if we &quot;represent&quot; our functors by exponentials, then we can work with them directly as exponentials as well, with all the usual rules. Edward Kmett has a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/representable-functors/3.0.0.1/doc/html/Data-Functor-Representable.html&quot;&gt;library encoding representable functors in Haskell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Meanwhile, Peter Hancock prefers to call such functors &lt;a href=&quot;http://sneezy.cs.nott.ac.uk/containers/blog/?p=14&quot;&gt;&quot;Naperian&quot;&lt;/a&gt; after John Napier, inventor of the logarithm (See also &lt;a href=&quot;http://stackoverflow.com/a/13100857/371753&quot;&gt;here&lt;/a&gt;). Why Naperian? Because if our functors are isomorphic to exponentials, then we can take their logs! And that brings us back to the initial discussion of type mathematics. We have some functor F, and claim that it is isomorphic to -^R for some concrete data type R. Well, this means that R is the logarithm of F. E.g. &lt;code&gt;(R -&amp;gt; a, S -&amp;gt; a) =~ Either R S -&amp;gt; a&lt;/code&gt;, which is to say that if log F = R and log G =~ S, then log (F * G) = log F + log G. Similarly, for any other data type n, again with log F = R, we have &lt;code&gt;n -&amp;gt; F a =~ n -&amp;gt; R -&amp;gt; a =~ (n * R) -&amp;gt; a&lt;/code&gt;, which is to say that log (F^n) =~ n * log F.&lt;/p&gt;
&lt;p&gt;This gives us one intuition for why the sum functor is not generally representable -- it is very difficult to decompose log (F + G) into some simpler compound expression of logs.&lt;/p&gt;
&lt;p&gt;So what functors are Representable? Anything that can be seen as a fixed shape with some index. Pairs, fixed-size vectors, fixed-size matrices, any nesting of fixed vectors and matricies. But also infinite structures of regular shape! However, not things whose shape can vary -- not lists, not sums. Trees of fixed depth or infinite binary trees therefore, but not trees of arbitrary depth or with ragged structure, etc.&lt;/p&gt;
&lt;p&gt;Representable functors turn out to be extremely powerful tools. Once we know a functor is representable, we know exactly what its applicative instance must be, and that its applicative instance will be &quot;zippy&quot; -- i.e. acting pointwise across the structure. We also know that it has a monad instance! And, unfortunately, that this monad instance is typically fairly useless (in that it is also &quot;zippy&quot; -- i.e. the monad instance on a pair just acts on the two elements pointwise, without ever allowing anything in the first slot to affect anything in the second slot, etc.). But we know more than that. We know that a representable functor, by virtue of being a reader in disguise, cannot have effects that migrate outwards. So any two actions in a representable functor are commutative. And more than that, they are entirely independent.&lt;/p&gt;
&lt;p&gt;This means that all representable functors are &quot;&lt;a href=&quot;https://hackage.haskell.org/packages/archive/distributive/0.3.1/doc/html/Data-Distributive.html&quot;&gt;distributive&lt;/a&gt;&quot;! Given any functor f, and any data type r, then we have&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;distributeReader&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f (r -&amp;gt; a) -&amp;gt; (r -&amp;gt; f a)
&lt;span class=&quot;hljs-title&quot;&gt;distributeReader&lt;/span&gt; fra = \r -&amp;gt; fmap ($r) fra
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is to say, given an arrow &quot;inside&quot; a functor, we can always pull the arrow out, and &quot;distribute&quot; application across the contents of the functor. A list of functions from &lt;code&gt;Int -&amp;gt; Int&lt;/code&gt; becomes a single function from &lt;code&gt;Int&lt;/code&gt; to a list of &lt;code&gt;Int&lt;/code&gt;, etc. More generally, since all representable functors are isomorphic to reader, given g representable, and f any functor, then we have: &lt;code&gt;distribute :: (Functor f, Representable g) =&amp;gt; f (g a) -&amp;gt; g (f a).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is pretty powerful sauce! And if f and g are &lt;em&gt;both&lt;/em&gt; representable, then we get the transposition isomorphism, witnessed by &lt;code&gt;flip&lt;/code&gt;! That's just the beginning of the good stuff. If we take functions and &quot;unrepresent&quot; them back to functors (i.e. take their logs), then we can do things like move from &lt;code&gt;((-&amp;gt;) Bool)&lt;/code&gt; to pairs, etc. Since we're in a pervasively lazy language, we've just created a library for &lt;a href=&quot;https://hackage.haskell.org/packages/archive/representable-tries/3.0.2/doc/html/Data-Functor-Representable-Trie.html&quot;&gt;memoization&lt;/a&gt;! This is because we've gone from a function to a data structure we can index into, representing each possible argument to this function as a &quot;slot&quot; in the structure. And the laziness pays off because we only need to evaluate the contents of each slot on demand (otherwise we'd have a precomputed lookup table rather than a dynamically-evaluated memo table).&lt;/p&gt;
&lt;p&gt;And now suppose we take our representable functor in the form &lt;code&gt;s -&amp;gt; a&lt;/code&gt; and paired it with an &quot;index&quot; into that function, in the form of a concrete &lt;code&gt;s&lt;/code&gt;. Then we'd be able to step that &lt;code&gt;s&lt;/code&gt; forward or backwards and navigate around our structure of &lt;code&gt;a&lt;/code&gt;s. And this is precisely the &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonads-fd/3.0.1/doc/html/Control-Comonad-Store.html&quot;&gt;Store Comonad&lt;/a&gt;! And this in turn gives a &lt;a href=&quot;http://patternsinfp.wordpress.com/2011/01/31/lenses-are-the-coalgebras-for-the-costate-comonad/&quot;&gt;characterization of the lens laws&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What this all gives us a tiny taste of, in fact, is the tremendous power of the &lt;a href=&quot;http://blog.sigfpe.com/2006/11/yoneda-lemma.html&quot;&gt;Yoneda lemma&lt;/a&gt;, which, in Haskell, is all about going between values and functions, and in fact captures the important universality and uniqueness properties that make working with representable functors tractable. A further tiny taste of Yoneda comes from a nice &lt;a href=&quot;http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization&quot;&gt;blog post&lt;/a&gt; by Conal Elliott on memoization.&lt;/p&gt;
&lt;h2 id=&quot;extra-credit-on-sum-functors&quot;&gt;Extra Credit on Sum Functors&lt;/h2&gt;
&lt;p&gt;There in fact is a log identity on sums. It goes like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;log&lt;/span&gt;(a + c) = log a + log (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + c/a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do you have a useful computational interpretation of this? I've got the inklings of one, but not much else.&lt;/p&gt;
&lt;h2 id=&quot;appendix-notes-on-representable-functors-in-hask&quot;&gt;Appendix: Notes on Representable Functors in Hask.&lt;/h2&gt;
&lt;p&gt;The way to think about this is to take some arbitrary category C, and some category that's basically Set (in our case, Hask. In fact, in our case, C is Hask too, and we're just talking about endofunctors on Hask). Now, we take some functor F : C -&amp;gt; Set, and some A which is an element of C. The set of morphisms originating at A (denoted by Hom(A,-)) constitutes a functor called the &quot;hom functor.&quot; For any object X in C, we can &quot;plug it in&quot; to Hom(A,-), to then get the set of all arrows from A to X. And for any morphism X -&amp;gt; Y in C, we can derive a morphism from Hom(A,X) to Hom(A,Y), by composition. This is equivalent to, in Haskell-land, using a function &lt;code&gt;f :: x -&amp;gt; y&lt;/code&gt; to send &lt;code&gt;g :: a -&amp;gt; x&lt;/code&gt; to &lt;code&gt;a -&amp;gt; y&lt;/code&gt; by writing &quot;functionAToY = f . g&quot;.&lt;/p&gt;
&lt;p&gt;So, for any A in C, we have a hom functor on C, which is C -&amp;gt; Set, where the elements of the resultant Set are homomorphisms in C. Now, we have this other arbitrary functor F, which is also C -&amp;gt; Set. Now, if there is an isomorphism of functors between F, and Hom(A,_), then we say F is &quot;representable&quot;. A representable functor is thus one that can be worked with entirely as an appropriate hom-functor.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/representing-applicatives/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Japanese “ekmett” Workshop (Part 1 of 2)</title><link>https://comonad.com/reader/2013/japanese-workshop-1/</link><guid isPermaLink="false">https://comonad.com/reader/2013/japanese-workshop-1/</guid><pubDate>Mon, 01 Apr 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 1 April 2013&lt;/p&gt;&lt;span id=&quot;more-831&quot;&gt;&lt;/span&gt;&lt;p&gt;A couple of weeks back one of my coworkers brought to my attention &lt;a href=&quot;http://partake.in/events/1698f7f8-4151-4048-b317-03a8c3f1a7ab&quot;&gt;a several hour long workshop in Japan&lt;/a&gt; to go over and describe a number of my libraries, hosted by &lt;a href=&quot;https://github.com/tanakh&quot;&gt;TANAKA Hideyuki&lt;/a&gt; — not the &lt;a href=&quot;http://en.wikipedia.org/wiki/Hideyuki_Tanaka&quot;&gt;voice actor&lt;/a&gt;, I checked!&lt;/p&gt;
&lt;p&gt;I was incredibly honored and I figured that if that many people (they had 30 or so registered attendees and 10 presentations) were going to spend that much time going over software that I had written, I should at least offer to show up!&lt;/p&gt;
&lt;p&gt;I'd like to apologize for any errors in the romanization of people's names or misunderstandings I may have in the following text. My grasp of Japanese is very poor! Please feel free to send me corrections or additions!&lt;/p&gt;
&lt;h2 id=&quot;surprise&quot;&gt;Surprise!&lt;/h2&gt;
&lt;p&gt;Sadly, my &lt;a href=&quot;https://twitter.com/mcscottmc&quot;&gt;boss&lt;/a&gt;'s immediate reaction to hearing that there was a workshop in Japan about my work was to quip that &quot;You're saying you're &lt;a href=&quot;http://en.wikipedia.org/wiki/Big_in_Japan_(phrase)&quot;&gt;huge in Japan&lt;/a&gt;?&quot; With him conspicuously not offering to fly me out here, I had to settle for surprising the organizers and attending via Google Hangout.&lt;/p&gt;
&lt;h2 id=&quot;commentary-and-logs&quot;&gt;Commentary and Logs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/nushio&quot;&gt;@nushio&lt;/a&gt; was very helpful in getting me connected, and while the speakers gave their talks I sat on the irc.freenode.net #haskell-lens channel and Google Hangout and answered questions and provided a running commentary with more details and references. Per &lt;a href=&quot;http://freenode.net/channel_guidelines.shtml&quot;&gt;freenode policy&lt;/a&gt; the fact that we were logging the channel was announced -- well, at least before things got too far underway.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/ekmett/5283253&quot;&gt;Here is the IRC session log as a gist&lt;/a&gt;. IKEGAMI Daisuke &lt;a href=&quot;https://twitter.com/ikegami__&quot;&gt;@ikegami__&lt;/a&gt; (&lt;code&gt;ikeg&lt;/code&gt; in the IRC log) tried to keep up a high-level running commentary about what was happening in the video to the log, which may be helpful if you are trying to follow along through each retroactively.&lt;/p&gt;
&lt;p&gt;Other background chatter and material is strewn across twitter under the &lt;a href=&quot;https://twitter.com/search?q=%23ekmett_conf&amp;src=typd&quot;&gt;#ekmett_conf&lt;/a&gt; hash tag and on a japanese twitter aggregator named &lt;a href=&quot;http://togetter.com/li/480399&quot;&gt;togetter&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;The 1PM start time in Shibuya, Tokyo, Japan translates to midnight at the start of Easter here in Boston, which meant ~6 hours later when we reached the Q&amp;amp;A session, I was a bit loopy from lack of sleep, but they were incredibly polite and didn't seem to mind my long rambling responses.&lt;/p&gt;
&lt;p&gt;Thanks to the organizers, we have video of the vast majority of the event! There was no audio for the first couple of minutes, and the recording machine lost power for the last talk and the Q&amp;amp;A session at the end as we ran somewhat longer than they had originally scheduled! -- And since I was attending remotely and a number of others flitted in and out over the course of the night, they were nice enough to put most of the slides and background material online.&lt;/p&gt;
&lt;h2 id=&quot;profunctors-by-liyang-hu-and-hibino-kei&quot;&gt;profunctors by Liyang HU and HIBINO Kei&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://liyang.hu/&quot;&gt;Liyang Hu&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/liyanghu&quot;&gt;@liyanghu&lt;/a&gt;) started the session off with a nicely self-contained crash course on my &lt;a href=&quot;http://github.com/ekmett/profunctors&quot;&gt;profunctors&lt;/a&gt; package, since profunctors are used fairly heavily inside the implementation of &lt;a href=&quot;http://github.com/ekmett/lens&quot;&gt;lens&lt;/a&gt; and &lt;a href=&quot;http://github.com/ekmett/machines&quot;&gt;machines&lt;/a&gt;, with a couple of detours into &lt;a href=&quot;http://github.com/ekmett/contravariant&quot;&gt;contravariant&lt;/a&gt; and &lt;a href=&quot;http://github.com/ekmett/bifunctors&quot;&gt;bifunctors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.fpcomplete.com/user/liyang/profunctors&quot;&gt;His presentation materials&lt;/a&gt; are available interactively from the new &lt;a href=&quot;https://www.fpcomplete.com/&quot;&gt;FP Complete&lt;/a&gt; School of Haskell. You can also watch the &lt;a href=&quot;http://www.ustream.tv/recorded/30668431/highlight/337429&quot;&gt;video recording of his talk&lt;/a&gt; on &lt;a href=&quot;http://www.ustream.tv/&quot;&gt;ustream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This talk was followed by a much more condensed version of very similar content &lt;a href=&quot;http://www.ustream.tv/recorded/30668431/highlight/337431&quot;&gt;in Japanese by Hibino Kei&lt;/a&gt; (&lt;a href=&quot;https://github.com/khibino&quot;&gt;@khibino&lt;/a&gt;) His talk was more focused on the relationship between arrows and profunctors, and the &lt;a href=&quot;http://www.slideshare.net/khibino/profunctor-and-arrow-17939130&quot;&gt;slides are available through slideshare&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lens-by-its-out-of-tune&quot;&gt;lens by @its_out_of_tune&lt;/h2&gt;
&lt;p&gt;Once the necessary background material was out of the way, the talk on &lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;lens&lt;/a&gt; -- arguably the presentation that most of the people were there for -- came early.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/assets/imported/395ece1374ab-ekmett_conf-its_out_of_tune-1.jpg&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/395ece1374ab-ekmett_conf-its_out_of_tune-1.jpg&quot; alt=&quot;ekmett_conf-its_out_of_tune-1&quot; title=&quot;ekmett_conf-its_out_of_tune-1&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/its_out_of_tune&quot;&gt;@its_out_of_tune&lt;/a&gt; gave an incredibly dense overview of how to use the main parts of the lens package in Japanese. &lt;a href=&quot;http://www.slideshare.net/itsoutoftunethismymusic/ekmett-17955009&quot;&gt;His slides are available online&lt;/a&gt; and &lt;a href=&quot;http://www.ustream.tv/recorded/30668431/highlight/337435&quot;&gt;here is a recording of his talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over the course of a half hour, he was able to cram in a great cross-section of the library including material that I hadn't even been able to get to even with 4x the amount of time available during &lt;a href=&quot;https://www.youtube.com/watch?v=cefnmjtAolY&amp;hd=1&quot;&gt;my New York talk&lt;/a&gt; on how to use the lens template-haskell code to automatically generate lenses for user data types and how to use the lens &lt;a href=&quot;https://hackage.haskell.org/packages/archive/lens/3.9.0.2/doc/html/Control-Lens-Action.html%22&quot;&gt;Action&lt;/a&gt; machinery.&lt;/p&gt;
&lt;h2 id=&quot;free-and-free-game-by-kinoshita-fumiaki&quot;&gt;free and free-game by KINOSHITA Fumiaki&lt;/h2&gt;
&lt;p&gt;Next up, was my &lt;a href=&quot;https://hackage.haskell.org/package/free&quot;&gt;free&lt;/a&gt; package and the neat &lt;a href=&quot;https://hackage.haskell.org/package/free-game&quot;&gt;free-game&lt;/a&gt; engine that Kinoshita Fumiaki (&lt;a href=&quot;https://twitter.com/fumieval&quot;&gt;@fumieval&lt;/a&gt;) built on top.&lt;/p&gt;
&lt;p&gt;The slides were in English, though the talk and humor were very Japanese. ^_^&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/assets/imported/0b7bcb748bf9-ekmett_conf-free.jpg&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/0b7bcb748bf9-ekmett_conf-free.jpg&quot; alt=&quot;ekmett_conf-free&quot; title=&quot;ekmett_conf-free&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That said, he had some amazingly nice demos, including a live demo of his tetris clone, &lt;a href=&quot;https://github.com/fumieval/Monaris&quot;&gt;Monaris&lt;/a&gt;, which is visible about 10 minutes into &lt;a href=&quot;http://www.ustream.tv/recorded/30668431/highlight/337437&quot;&gt;the video&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;ad-by-nebutalab&quot;&gt;ad by @nebutalab&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/nebutalab&quot;&gt;@nebutalab&lt;/a&gt;, like me, joined the session remotely through Google Hangout, and proceeded to give a tutorial on how &lt;a href=&quot;http://en.wikipedia.org/wiki/Automatic_differentiation#Forward_accumulation&quot;&gt;forward mode&lt;/a&gt; automatic differentiation works through my &lt;a href=&quot;http://github.com/ekmett/ad&quot;&gt;AD&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.slideshare.net/nebuta/haskell-ad34&quot;&gt;His slides were made available before the talk&lt;/a&gt; and the video is available in &lt;a href=&quot;http://www.ustream.tv/recorded/30671273/highlight/337441&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;http://www.ustream.tv/recorded/30671623/highlight/337439&quot;&gt;parts&lt;/a&gt; due a technical hiccup in the middle of the recording.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/assets/imported/75ac483beaba-ekmett_conf-ad.jpg&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/6cd7fee5d1b3-ekmett_conf-ad-300x204.jpg&quot; alt=&quot;ekmett_conf-ad&quot; title=&quot;ekmett_conf-ad&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'm currently working to drastically simplify the API for ad with &lt;a href=&quot;https://github.com/alang9&quot;&gt;Alex Lang&lt;/a&gt;. Fortunately almost all of the material in this presentation will still be relevant to the new design.&lt;/p&gt;
&lt;h2 id=&quot;tables-by-murayama-shohei&quot;&gt;tables by MURAYAMA Shohei&lt;/h2&gt;
&lt;p&gt;Next up, Murayama Shohei (&lt;a href=&quot;https://twitter.com/yuga&quot;&gt;@yuga&lt;/a&gt;) gave an introduction to &lt;a href=&quot;https://hackage.haskell.org/package/tables&quot;&gt;tables&lt;/a&gt;, which is a small in memory data-store that I wrote a few months back to sit on top of lens.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ustream.tv/recorded/30672629/highlight/337395&quot;&gt;Video of @yuga's talk&lt;/a&gt; and &lt;a href=&quot;https://gist.github.com/yuga/5279313&quot;&gt;his slides&lt;/a&gt; are available, which I think makes this the first public talk about this project. -_^&lt;/p&gt;
&lt;h2 id=&quot;machines-by-yoshida-sanshiro&quot;&gt;machines by YOSHIDA Sanshiro&lt;/h2&gt;
&lt;p&gt;Yoshida Sanshiro (&lt;a href=&quot;http://twitter.com/halcat0x15a&quot;&gt;@halcat0x15a&lt;/a&gt;) gave a nice overview of the currently released version of &lt;a href=&quot;https://hackage.haskell.org/package/machines&quot;&gt;machines&lt;/a&gt; including a lot of examples! I think he may have actually written more code using machines just for demonstrations than I have written using it myself.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ustream.tv/recorded/30672629/highlight/337397&quot;&gt;Video of his talk is available&lt;/a&gt; along with &lt;a href=&quot;http://halcat0x15a.github.com/slide/machines/out/#0&quot;&gt;his slide deck&lt;/a&gt; -- just tap left or right to move through the slides. He has also written &lt;a href=&quot;http://krdlab.hatenablog.com/entry/2013/03/16/204039&quot;&gt;a blog post&lt;/a&gt; documenting his early explorations of the library, and some thoughts about using it with attoparsec.&lt;/p&gt;
&lt;p&gt;I've recently been trying to redesign machines with coworker Paul CHIUSANO &lt;a href=&quot;https://twitter.com/pchiusano&quot;&gt;@pchiusano&lt;/a&gt; and we've begun greatly simplifying the design of machines based on some work &lt;a href=&quot;http://www.youtube.com/watch?v=8fC2V9HX_m8&quot;&gt;he has been doing in Scala&lt;/a&gt;, so unfortunately many of the particulars of this talk will be soon outdated, but the overall 'feel' of working with machines should be preserved across the change-over. Some of these changes can be seen in the &lt;a href=&quot;http://github.com/ekmett/machines&quot;&gt;master branch on github&lt;/a&gt; now.&lt;/p&gt;
&lt;h2 id=&quot;more-to-come&quot;&gt;More to come&lt;/h2&gt;
&lt;p&gt;There were 4 more sessions, but alas, I'm out of time for the moment! I'll continue this write-up with more links to the source material and my thoughts as soon as I can tomorrow!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/japanese-workshop-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Algebras of Applicatives</title><link>https://comonad.com/reader/2013/algebras-of-applicatives/</link><guid isPermaLink="false">https://comonad.com/reader/2013/algebras-of-applicatives/</guid><pubDate>Fri, 11 Jan 2013 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 11 January 2013&lt;/p&gt;&lt;p&gt;While the &lt;a href=&quot;https://comonad.com/reader/2012/abstracting-with-applicatives/&quot;&gt;previous post&lt;/a&gt; in this series was relatively immediately applicable, this one has constructions I definitely wouldn't recommend in production code. However, they do take us further in exploring the universe of applicative functors, and, more broadly, exploring which data types provide which properties by construcion.&lt;/p&gt;
&lt;p&gt;It's well known that if you have any Functor &lt;code&gt;F a&lt;/code&gt;, you can take its &quot;fixpoint&quot;, creating a structure of infinitely nested Fs, like so. &lt;code&gt;F (F (F (...) ) )&lt;/code&gt; Since we can't have infinite types directly in Haskell, we introduce the Fix newtype:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fix&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &quot;wraps up&quot; the recursion so that GHC accepts the type. &lt;code&gt;Fix f&lt;/code&gt; is a &lt;code&gt;Fix&lt;/code&gt; constructor, containing an &quot;f&quot; of &lt;code&gt;Fix f&lt;/code&gt; inside. Each in turn expands out, and soforth. Fixpoints of functors have fixedpoints of functors inside 'em. And so on, and so on, ad infinitum.&lt;/p&gt;
&lt;p&gt;(Digression: We speak of &quot;algebraic data types&quot; in Haskell. The &quot;algebra&quot; in question is an &quot;F-algebra&quot;, and we can build up structures with fixpoints of functors, taking those functors as initial or terminal objects and generating either initial algebras or terminal coalgebras. These latter two concepts coincide in Haskell in the Fix description given above, as greatest and least fixpoints of data types in Haskell turn out to be the same thing. For more background, one can go to Wadler's &quot;&lt;a href=&quot;http://homepages.inf.ed.ac.uk/wadler/papers/free-rectypes/free-rectypes.txt&quot;&gt;Recursive Types for Free&lt;/a&gt;,&quot; or Jacobs and Rutten's &quot;&lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.1418&quot;&gt;Tutorial on (Co)Algebras and (Co)Induction&lt;/a&gt;&quot; for starters.)&lt;/p&gt;
&lt;p&gt;The family of functors built from our friends Const, Sum, Product, and Reader (exponentiation) are known as Polynomial Functors. If we take closure of these with a proper fixpoint construct (that lets us build infinite structures), we get things that are variously known as Containers, Shapely Types, and Strictly Positive types.&lt;/p&gt;
&lt;p&gt;One irritating thing is that the fixpoint of a functor as we've written it is no longer itself a functor. The type constructor Fix is of kind &lt;code&gt;(* -&amp;gt; *) -&amp;gt; *&lt;/code&gt;, which says it takes an &quot;f&quot; which takes one argument (e.g. &quot;Maybe&quot; or &quot;Identity&quot; or etc.) and returns a proper type (i.e. a value at the type level of kind *).&lt;/p&gt;
&lt;p&gt;We want a fixpoint construction that gives back something of kind &lt;code&gt;* -&amp;gt; *&lt;/code&gt; — i.e. something that is a type constructor representing a functor, and not just a plain old type. The following does the trick.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) a)&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (f (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; f) a)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(I learned about FixF from &lt;a href=&quot;http://www.cs.ox.ac.uk/ralf.hinze/SSGIP10/AdjointFolds.pdf&quot;&gt;a paper by Ralf Hinze&lt;/a&gt;, but I'm sure the origins go back much further).&lt;/p&gt;
&lt;p&gt;FixF is of kind &lt;code&gt;((* -&amp;gt; *) -&amp;gt; * -&amp;gt; *) -&amp;gt; * -&amp;gt; *&lt;/code&gt;. It takes the fixpoint of a &quot;second-order Functor&quot; (a Functor that sends a Functor to another Functor, i.e. an endofunctor on the functor category of hask), to recover a standard &quot;first order Functor&quot; back out. This sounds scary, but it isn't once you load it up in ghci and start playing with it. In fact, we've encountered second order functors just recently. Product, Sum, and Compose are all of kind &lt;code&gt;(* -&amp;gt; *) -&amp;gt; (* -&amp;gt; *) -&amp;gt; * -&amp;gt; *&lt;/code&gt;. So they all send two functors to a third functor. That means that &lt;code&gt;Product Const&lt;/code&gt;, &lt;code&gt;Sum Identity&lt;/code&gt; and &lt;code&gt;Compose Maybe&lt;/code&gt; are all second-order functors, and things appropriate to take our &quot;second-order fixpoint&quot; of.&lt;/p&gt;
&lt;p&gt;Conceptually, &quot;Fix f&quot; took a value with one hole, and we filled that hole with &quot;Fix f&quot; so there was no room for a type parameter. Now we've got an &quot;f&quot; with two holes, the first of which takes a functor, and the second of which is the hole of the resulting functor.&lt;/p&gt;
&lt;p&gt;Unlike boring old &quot;Fix&quot;, we can write Functor and Applicative instances for &quot;FixF&quot;, and they're about as simple and compositional as we could possibly hope.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; $ fmap f x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure x = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; $ pure x
    (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; (f &amp;lt; *&amp;gt; x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now we run into a new problem! It seems like this &quot;a&quot; parameter is just hanging out there, doing basically nothing. We take our classic functors and embed them in there, and they still only have &quot;one hole&quot; at the value level, so don't actually have any place to put the &quot;a&quot; type we now introduced. For example, we can write the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- FixF . Compose . Just . FixF . Compose $ Nothing&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Compose (Just (FixF (Compose Nothing))))&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- :t FixF (Compose (Just (FixF (Compose Nothing))))&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Compose Maybe) a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now introduce one new member of our basic constructions — a second order functor that acts like &quot;const&quot; on the type level, taking any functor and returning Identity.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: * -&amp;gt; *) a = &lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; $ f x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure x = &lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; x
    (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; (f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can actually stick functorial values into our fixpoints:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- FixF $ Embed &quot;hi&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Embed &quot;hi&quot;)&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- fmap (++ &quot; world&quot;) $ FixF (Embed &quot;hi&quot;)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Embed &quot;hi world&quot;)&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- FixF . Product (Embed &quot;hi&quot;) .&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--        FixF . Product (Embed &quot;there&quot;) . FixF $ undefined&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Product (Embed &quot;hi&quot;)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--   (FixF (Product (Embed &quot;there&quot;)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--   (FixF *** Exception: Prelude.undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may have noticed that we seem to be able to use &quot;product&quot; to begin a chain of nested fixpoints, but we don't seem able to stick a &quot;Maybe&quot; in there to &lt;strong&gt;stop&lt;/strong&gt; the chain. And it seems like we're not even &quot;fixing&quot; where we intend to be:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- :t FixF . Product (Embed &quot;hi&quot;) . FixF . Product (Embed &quot;there&quot;) . FixF $ undefined&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (Product (Embed f)) [Char]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's because we're applying Product, takes and yields arguments of kind &lt;code&gt;* -&amp;gt; *&lt;/code&gt; in a context where we really want to take and yield second-order functors as arguments — things of kind &lt;code&gt;(* -&amp;gt; *) -&amp;gt; * -&amp;gt; *&lt;/code&gt;. If we had proper kind polymorphism, &quot;Product&quot; and &quot;ProductF&quot; would be able to collapse (and maybe, soon, they will). But at least in the ghc 7.4.1 that I'm working with, we have to write the same darn thing, but &quot;up a kind&quot;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; f g (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; :: * -&amp;gt; *) a =&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (f b a) (g b a) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
                fmap f (&lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; x y) = &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (fmap f x) (fmap f y)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) =&amp;gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
               pure x = &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (pure x) (pure x)
              (&lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; f g) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; x y) = &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (f &amp;lt; *&amp;gt; x) (g &amp;lt; *&amp;gt; y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now do the following properly.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;yy&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;foo&quot;&lt;/span&gt;) $ &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;xx&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;bar&quot;&lt;/span&gt;) . &lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; .
  &lt;span class=&quot;hljs-type&quot;&gt;FixF&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;ProductF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Embed&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;baz&quot;&lt;/span&gt;) . &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we've recovered proper lists in Haskell, as the &quot;second-order fixpoint&quot; of polynomial functors. And the types look right too:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- :t yy&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (ProductF Embed (Sum (Const ()))) [Char]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we've built our Applicative instances compositionally, we have an applicative for our list list construction automatically:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- (++) &amp;lt; $&amp;gt; yy &amp;lt; *&amp;gt; xx&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; FixF (ProductF (Embed &quot;foobar&quot;) (InL (Const ())))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is precisely the &quot;ZipList&quot; applicative instance. In fact, our applicative instances from this &quot;functor toolkit&quot; are all &quot;zippy&quot; — matching up structure where possible, and &quot;smashing it down&quot; where not. This is because Sum, with its associated natural transformation logic, is the only way to introduce a disjoint choice of shape. Here are some simple examples with Sum to demonstrate:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- liftA2 (++) (InL (Identity &quot;hi&quot;)) $&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--      InR (Product (Identity &quot; there&quot;) (Const ([12::Int])))&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; InL (Identity &quot;hi there&quot;)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- liftA2 (++) (InR (Identity &quot;hi&quot;)) $ InL (Product (Identity &quot; there&quot;) (Const ([12::Int])))&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; InL (Product (Identity &quot;hi there&quot;) (Const [12]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We're always &quot;smashing&quot; towards the left. So in the first case, that means throwing away half of the pair. In the second case, it means injecting Const mempty into a pair, and then operating with that.&lt;/p&gt;
&lt;p&gt;In any case, we now have infinite and possibly infinite branching structures. And not only are they Functors, but they're also Applicatives, and in a way that's uniform and straightforward to reason about.&lt;/p&gt;
&lt;p&gt;In the next post, we'll stop building out our vocabulary of &quot;base&quot; Functors (though it's not quite complete) and instead push forward on what else these functors can provide &quot;beyond&quot; Applicative.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2013/algebras-of-applicatives/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The Ermine programming language</title><link>https://comonad.com/reader/talks/kmett-2013-ermine-boston/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2013-ermine-boston/</guid><category>Talk</category><description>&lt;p&gt;Edward Kmett · 2013 · day unknown&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;QCvXlOCBe5A&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=QCvXlOCBe5A&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The Ermine programming language — Boston Haskell.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=QCvXlOCBe5A&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2013-ermine-boston/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Abstracting with Applicatives</title><link>https://comonad.com/reader/2012/abstracting-with-applicatives/</link><guid isPermaLink="false">https://comonad.com/reader/2012/abstracting-with-applicatives/</guid><pubDate>Wed, 26 Dec 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Gershom Bazerman · 26 December 2012&lt;/p&gt;&lt;p&gt;Consider the humble Applicative. More than a functor, less than a monad. It gives us such lovely syntax. Who among us still prefers to write &lt;code&gt;liftM2 foo a b&lt;/code&gt; when we could instead write &lt;code&gt;foo &amp;lt;$&amp;gt; a &amp;lt;*&amp;gt; b&lt;/code&gt;? But we seldom use the Applicative as such — when Functor is too little, Monad is too much, but a lax monoidal functor is just right. I noticed lately a spate of proper uses of Applicative —&lt;a href=&quot;http://groups.inf.ed.ac.uk/links/formlets/&quot;&gt;Formlets&lt;/a&gt; (and their later incarnation in the &lt;a href=&quot;https://hackage.haskell.org/package/reform&quot;&gt;reform&lt;/a&gt; library), &lt;a href=&quot;https://hackage.haskell.org/package/optparse-applicative&quot;&gt;OptParse-Applicative&lt;/a&gt; (and its competitor library &lt;a href=&quot;https://comonad.com/reader/2012/abstracting-with-applicatives/&quot;&gt;CmdTheLine&lt;/a&gt;), and a &lt;a href=&quot;http://gergo.erdi.hu/blog/2012-12-01-static_analysis_with_applicatives/&quot;&gt;post by Gergo Erdi&lt;/a&gt; on applicatives for declaring dependencies of computations. I also ran into a very similar genuine use for applicatives in working on the Panels library (part of &lt;a href=&quot;https://hackage.haskell.org/package/jmacro-rpc&quot;&gt;jmacro-rpc&lt;/a&gt;), where I wanted to determine dependencies of a dynamically generated dataflow computation. And then, again, I stumbled into an applicative while cooking up a form validation library, which turned out to be a reinvention of the same ideas as formlets.&lt;/p&gt;
&lt;p&gt;Given all this, It seems post on thinking with applicatives is in order, showing how to build them up and reason about them. One nice thing about the approach we'll be taking is that it uses a &quot;final&quot; encoding of applicatives, rather than building up and then later interpreting a structure. This is in fact how we typically write monads (pace operational, free, etc.), but since we more often only determine our data structures are applicative after the fact, we often get some extra junk lying around (OptParse-Applicative, for example, has a GADT that I think is entirely extraneous).&lt;/p&gt;
&lt;p&gt;So the usual throat clearing:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE TypeOperators, MultiParamTypeClasses, FlexibleInstances,
StandaloneDeriving, FlexibleContexts, UndecidableInstances,
GADTs, KindSignatures, RankNTypes #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Main &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Identity
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    show (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; x) = &lt;span class=&quot;hljs-string&quot;&gt;&quot;(Identity &quot;&lt;/span&gt; ++ show x ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;)&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now, let's start with a classic applicative, going back to the &lt;a href=&quot;http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf&quot;&gt;Applicative Programming With Effects&lt;/a&gt; paper:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo a = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap _ (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo) = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; mo =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure _ = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mempty
    (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; (f &amp;lt;&amp;gt; x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;code&gt;Const&lt;/code&gt; lives in &lt;a href=&quot;https://hackage.haskell.org/package/transformers&quot;&gt;transformers&lt;/a&gt; as the &lt;code&gt;Constant&lt;/code&gt; functor, or in base as &lt;code&gt;Const&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;Const&lt;/code&gt; is not a monad. We've defined it so that its structure is independent of the `a` type. Hence if we try to write &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; of type &lt;code&gt;Const mo a -&amp;gt; (a -&amp;gt; Const mo b) -&amp;gt; Const mo b&lt;/code&gt;, we'll have no way to &quot;get out&quot; the first `a` and feed it to our second argument.&lt;/p&gt;
&lt;p&gt;One great thing about Applicatives is that there is no distinction between applicative transformers and applicatives themselves. This is to say that the composition of two applicatives is cleanly and naturally always also an applicative. We can capture this like so:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; $ (fmap . fmap) f x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . pure . pure
    (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; $ (&amp;lt; *&amp;gt;) &amp;lt; $&amp;gt; f &amp;lt; *&amp;gt; x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;code&gt;Compose&lt;/code&gt; also lives in transformers)&lt;/p&gt;
&lt;p&gt;Note that Applicatives compose &lt;strong&gt;two&lt;/strong&gt; ways. We can also write:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt;  x y) = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (fmap f x) (fmap f y)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (pure x) (pure x)
    (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; f g) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt;  x y) = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (f &amp;lt; *&amp;gt; x) (g &amp;lt; *&amp;gt; y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;code&gt;Product&lt;/code&gt; lives in transformers as well)&lt;/p&gt;
&lt;p&gt;This lets us now construct an extremely rich set of applicative structures from humble beginnings. For example, we can reconstruct the Writer Applicative.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Writer&lt;/span&gt; mo = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;tell&lt;/span&gt; :: mo -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Writer&lt;/span&gt; mo ()
&lt;span class=&quot;hljs-title&quot;&gt;tell&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x) (pure ())
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- tell [1] *&amp;gt; tell [2]&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; Product (Const [1,2]) (Identity ())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that if we strip away the newtype noise, Writer turns into &lt;code&gt;(mo,a)&lt;/code&gt; which is isomorphic to the Writer monad. However, we've learned something along the way, which is that the monoidal component of Writer (as long as we stay within the rules of applicative) is entirely independent from the &quot;identity&quot; component. However, if we went on to write the Monad instance for our writer (by defining &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;), we'd have to &quot;reach in&quot; to the identity component to grab a value to hand back to the function yielding our monoidal component. Which is to say we would destroy this nice seperation of &quot;trace&quot; and &quot;computational content&quot; afforded by simply taking the product of two Applicatives.&lt;/p&gt;
&lt;p&gt;Now let's make things more interesting. It turns out that just as the composition of two applicatives may be a monad, so too the composition of two monads may be no stronger than an applicative!&lt;/p&gt;
&lt;p&gt;We'll see this by introducing Maybe into the picture, for possibly failing computations.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FailingWriter&lt;/span&gt; mo = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Writer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;tellFW&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; mo =&amp;gt; mo -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FailingWriter&lt;/span&gt; mo ()
&lt;span class=&quot;hljs-title&quot;&gt;tellFW&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (tell x *&amp;gt; pure (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; ()))

&lt;span class=&quot;hljs-title&quot;&gt;failFW&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; mo =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FailingWriter&lt;/span&gt; mo a
&lt;span class=&quot;hljs-title&quot;&gt;failFW&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (pure &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- tellFW [1] *&amp;gt; tellFW [2]&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; Compose (Product (Const [1,2]) (Identity Just ()))&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- tellFW [1] *&amp;gt; failFW *&amp;gt; tellFW [2]&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- &amp;gt; Compose (Product (Const [1,2]) (Identity Nothing))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Maybe over Writer gives us the same effects we'd get in a Monad — either the entire computation fails, or we get the result and the trace. But Writer over Maybe gives us new behavior. We get the entire trace, even if some computations have failed! This structure, just like Const, cannot be given a proper Monad instance. (In fact if we take Writer over Maybe as a Monad, we get only the trace until the first point of failure).&lt;/p&gt;
&lt;p&gt;This seperation of a monoidal trace from computational effects (either entirely independent of a computation [via a product] or independent between parts of a computation [via Compose]) is the key to lots of neat tricks with applicative functors.&lt;/p&gt;
&lt;p&gt;Next, let's look at Gergo Erdi's &quot;Static Analysis with Applicatives&quot; that is built using free applicatives. We can get essentially the same behavior directly from the product of a constant monad with an arbitrary effectful monad representing our ambient environment of information. As long as we constrain ourselves to only querying it with the takeEnv function, then we can either read the left side of our product to statically read dependencies, or the right side to actually utilize them.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HasEnv&lt;/span&gt; k m = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; [&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;]) m&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;takeEnv&lt;/span&gt; :: (k -&amp;gt; m a) -&amp;gt; k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HasEnv&lt;/span&gt; k m a
&lt;span class=&quot;hljs-title&quot;&gt;takeEnv&lt;/span&gt; f x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; [x]) (f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we prefer, we can capture queries of a static environment directly with the standard Reader applicative, which is just a newtype over the function arrow. There are other varients of this that perhaps come closer to exactly how Erdi's post does things, but I think this is enough to demonstrate the general idea.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; r a = &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; (f . x)
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure x = &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; $ pure x
    (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; (f &amp;lt; *&amp;gt; x)

&lt;span class=&quot;hljs-title&quot;&gt;runReader&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; r a) -&amp;gt; r -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runReader&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; f) = f

&lt;span class=&quot;hljs-title&quot;&gt;takeEnvNew&lt;/span&gt; :: (env -&amp;gt; k -&amp;gt; a) -&amp;gt; k -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;HasEnv&lt;/span&gt; k (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; env) a
&lt;span class=&quot;hljs-title&quot;&gt;takeEnvNew&lt;/span&gt; f x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; [x]) (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; $ flip f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, what then is a full formlet? It's something that can be executed in one context as a monoid that builds a form, and in another as a parser. so the top level must be a product.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FormletOne&lt;/span&gt; mo a = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Below the product, we read from an environment and perhaps get an answer. So that's reader with a maybe.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FormletTwo&lt;/span&gt; mo env a =&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo) (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; env) &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt;) a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if we fail, we want to have a trace of errors. So we expand out the Maybe into a product as well to get the following, which adds monoidal errors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FormletThree&lt;/span&gt; mo err env a =&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo)
            (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; env) (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; err) &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt;)) a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now we get errors whether or not the parse succeeds. We want to say either the parse succeeds or we get errors. For this, we can turn to the typical Sum functor, which currently lives as Coproduct in comonad-transformers, but will hopefully be moving as Sum to the transformers library in short order.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (fmap f x)
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; y) = &lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; (fmap f y)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Functor instance is straightforward for Sum, but the applicative instance is puzzling. What should &quot;pure&quot; do? It needs to inject into either the left or the right, so clearly we need some form of &quot;bias&quot; in the instance. What we really need is the capacity to &quot;work in&quot; one side of the sum until compelled to switch over to the other, at which point we're stuck there. If two functors, F and G are in a relationship such that we can always send &lt;code&gt;f x -&amp;gt; g x&lt;/code&gt; in a way that &quot;respects&quot; fmap (that is to say, such that (&lt;code&gt;fmap f . fToG == ftoG . fmap f&lt;/code&gt;) then we call this a natural transformation. The action that sends f to g is typically called &quot;eta&quot;. (We actually want something slightly stronger called a &quot;monoidal natural transformation&quot; that respects not only the functorial action &lt;code&gt;fmap&lt;/code&gt; but the applicative action &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, but we can ignore that for now).&lt;/p&gt;
&lt;p&gt;Now we can assert that as long as there is a natural transformation between g and f, then Sum f g can be made an Applicative, like so:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; f g &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta :: f a -&amp;gt; g a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    pure x = &lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; $ pure x
    (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (f &amp;lt; *&amp;gt; x)
    (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; g) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; y) = &lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; (g &amp;lt; *&amp;gt; y)
    (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; f) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (f &amp;lt; *&amp;gt; eta x)
    (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; g) &amp;lt; *&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (eta g &amp;lt; *&amp;gt; x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The natural transformation we'll tend to use simply sends any functor to Const.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; mo =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta = const (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mempty)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, there are plenty of other natural transformations that we could potentially make use of, like so:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
     eta = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . pure
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
     eta = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap pure
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; x (eta x)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; g (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta x = &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (eta x) x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; x _ ) = x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) g &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; _ x) = x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; g f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta (&lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; x) = x
    eta (&lt;span class=&quot;hljs-type&quot;&gt;InR&lt;/span&gt; y) = eta y
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    eta (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; x) = pure x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In theory, there should also be a natural transformation that can be built magically from the product of any other two natural transformations, but that will just confuse the Haskell typechecker hopelessly. This is because we know that often different &quot;paths&quot; of typeclass choices will often be isomorphic, but the compiler has to actually pick one &quot;canonical&quot; composition of natural transformations to compute with, although multiple paths will typically be possible.&lt;/p&gt;
&lt;p&gt;For similar reasons of avoiding overlap, we can't both have the terminal homomorphism that sends everything to &quot;Const&quot; &lt;strong&gt;and&lt;/strong&gt; the initial homomorphism that sends &quot;Identity&quot; to anything like so:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- instance Applicative g =&amp;gt; Natural Identity g where&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--     eta (Identity x) = pure x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We choose to keep the terminal transformation around because it is more generally useful for our purposes. As the comments below point out, it turns out that a version of &quot;Sum&quot; with the initial transformation baked in now lives in transformers as &lt;code&gt;Lift&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In any case we can now write a proper Validation applicative:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Validation&lt;/span&gt; mo = &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;validationError&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; mo =&amp;gt; mo -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Validation&lt;/span&gt; mo a
&lt;span class=&quot;hljs-title&quot;&gt;validationError&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;InL&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This applicative will yield either a single result, or an accumulation of monoidal errors. It exists on hackage in the &lt;a href=&quot;https://hackage.haskell.org/package/Validation&quot;&gt;Validation&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;Now, based on the same principles, we can produce a full Formlet.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Formlet&lt;/span&gt; mo err env a =&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; mo)
            (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; env)
                     (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; err) &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;))
    a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All the type and newtype noise looks a bit ugly, I'll grant. But the idea is to &lt;strong&gt;think&lt;/strong&gt; with structures built with applicatives, which gives guarantees that we're building applicative structures, and furthermore, structures with certain guarantees in terms of which components can be interpreted independently of which others. So, for example, we can strip away the newtype noise and find the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FormletClean&lt;/span&gt; mo err env a = (&lt;span class=&quot;hljs-title&quot;&gt;mo&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;env&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we built this up from our basic library of applicatives, we also know how to write its applicative instance directly.&lt;/p&gt;
&lt;p&gt;Now that we've gotten a basic algebraic vocabulary of applicatives, and especially now that we've produced this nifty Sum applicative (which I haven't seen presented before), we've gotten to where I intended to stop.&lt;/p&gt;
&lt;p&gt;But lots of other questions arise, on two axes. First, what other typeclasses beyond applicative do our constructions satisfy? Second, what basic pieces of vocabulary are missing from our constructions — what do we need to add to flesh out our universe of discourse? (Fixpoints come to mind).&lt;/p&gt;
&lt;p&gt;Also, what statements can we make about &quot;completeness&quot; — what portion of the space of all applicatives can we enumerate and construct in this way? Finally, why is it that monoids seem to crop up so much in the course of working with Applicatives? I plan to tackle at least some of these questions in future blog posts.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/abstracting-with-applicatives/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Lenses, Folds and Traversals</title><link>https://comonad.com/reader/talks/kmett-2012-lenses-nyc/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2012-lenses-nyc/</guid><pubDate>Wed, 12 Dec 2012 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 12 December 2012&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;cefnmjtAolY&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cefnmjtAolY&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Lenses, Folds and Traversals — New York Haskell.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cefnmjtAolY&quot;&gt;video&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://comonad.com/haskell/Lenses-Folds-and-Traversals-NYC.pdf&quot;&gt;slides pdf&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2012-lenses-nyc/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Natural Deduction, Sequent Calculus and Type Classes</title><link>https://comonad.com/reader/2012/natural-deduction-sequent-calculus-and-type-classes/</link><guid isPermaLink="false">https://comonad.com/reader/2012/natural-deduction-sequent-calculus-and-type-classes/</guid><pubDate>Fri, 07 Dec 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 7 December 2012&lt;/p&gt;&lt;p&gt;By and large, there are two sorts of proof systems that people use (these days) when studying logic: natural deduction, and sequent calculus. I know of at least one other---Hilbert style---but it is older, and the above systems were invented due to dissatisfaction with Hilbert systems (for a programming analogy, Hilbert systems are like programming entirely with combinators (S, K, etc.), rather than a lambda calculus).&lt;/p&gt;
&lt;h2 id=&quot;natural-deduction&quot;&gt;Natural Deduction&lt;/h2&gt;
&lt;p&gt;Probably the best way to categorize the difference, for the purpose of where we're eventually going, is that natural deduction focuses on the ways to build proof terms up from their constituent parts. This comes in the form of introduction and elimination rules for the various propositions. For instance, the rules for conjunction are:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-I&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{A \,\,\,\,\,\,\,\,\, B}{A \wedge B}\;\wedge\text{-I}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2173em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8723em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-E1&lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-E2&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{A \wedge B}{A}\;\wedge\text{-E1} \,\,\,\,\,\, \frac{A \wedge B}{B}\;\wedge\text{-E2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2173em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8723em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2173em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E1&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8723em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This spartan style gets a bit annoying (in my opinion) for the hypothetical premises of the implication introduction, but this can be solved by adding contexts:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;-I&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, A \vdash B}{\Gamma \vdash A \rightarrow B}\;\rightarrow\text{-I} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2772em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;-E&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash A \rightarrow B \,\,\,\,\,\,\,\,\, \Gamma \vdash A}{\Gamma \vdash B}\;\rightarrow\text{-E} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is the style most commonly adopted for presenting type theories, except we reason about terms with a type, rather than just propositions. The context we added for convenience above also becomes fairly essential for keeping track of variables:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext&gt;-I&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : A \,\,\,\,\,\,\,\,\, \Gamma \vdash N : B}{\Gamma \vdash (M, N) : A \times B}\;\times\text{-I} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4001em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;f&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext&gt;-E1&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : A \times B}{\Gamma \vdash \mathsf{fst}\, M : A}\;\times\text{-E1} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot;&gt;fst&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext&gt;-E2&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : A \times B}{\Gamma \vdash \mathsf{snd}\, M : B}\;\times\text{-E2} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot;&gt;snd&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;λ&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;-I&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, x : A \vdash M : B}{\Gamma \vdash (\lambda x:A. \,\, M) : A \rightarrow B}\;\rightarrow\text{-I} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4522em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;λ&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mtext&gt;-E&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : A \rightarrow B \,\,\,\,\,\,\,\,\, \Gamma \vdash N : A}{\Gamma \vdash M \, N : B}\;\rightarrow\text{-E} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As can be seen, all the rules involve taking terms from the premise and building on them in the conclusion.&lt;/p&gt;
&lt;h2 id=&quot;sequent-calculi&quot;&gt;Sequent Calculi&lt;/h2&gt;
&lt;p&gt;The other type of system in question, sequent calculus, looks very similar, but represents a subtle shift in focus for our purposes (sequent calculi are a lot more obviously different when presenting classical logics). First, the inference rules relate sequents, which look a lot like our contextual judgments above, and I'll write them the same way. The difference is that not all rules operate on the conclusion side; some operate just on the context. Generally, introduction rules stay similar to natural deduction (and are called right rules), while elimination rules are replaced by manipulations of the context, and are called left rules. For pairs, we can use the rules:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-R&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash A \,\,\,\,\,\,\,\,\, \Gamma \vdash B}{\Gamma \vdash A \wedge B}\;\wedge\text{-R} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-L&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, A, B \vdash C}{\Gamma, A \wedge B \vdash C}\;\wedge\text{-L} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4133em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We could also have two separate left rules:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-L1&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{\Gamma, A \vdash C}{\Gamma, A \wedge B \vdash C}\;\wedge\text{-L1}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4133em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-L1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mtext&gt;-L2&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{\Gamma, B \vdash C}{\Gamma, A \wedge B \vdash C}\;\wedge\text{-L2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4133em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-L2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But these two different sets are equivalent as long as we're not considering substructural logics. Do note, however, that we're moving from &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; on the top left to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \wedge B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; on the bottom left, using the fact that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∧&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \wedge B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∧&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is sufficient to imply &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. That is, projections apply contravariantly to the left.&lt;/p&gt;
&lt;p&gt;It turns out that almost no type theory is done in this style; natural deduction is far and away more popular. There are, I think, a few reasons for this. The first is: how do we even extend the left rules to type theory (eliminations are obvious, by contrast)? I know of two ways. The first is to introduce pattern matching into the contexts, so our left rule becomes:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext&gt;-L&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, x : A, y : B \vdash M : C}{\Gamma, (x, y) : A \times B \vdash M : C}\;\times\text{-L} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4522em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is an acceptable choice (and may avoid some of the pitfalls in the next option), but it doesn't gel with your typical lambda calculus. It's probably more suited to a pattern calculus of some sort (although, even then, if you want to bend your brain, go look at the left rule for implication and try to figure out how it translates into such a theory; I think you probably need higher-order contexts of some sort). Anyhow, I'm not going to explore this further.&lt;/p&gt;
&lt;p&gt;The other option (and one that I've seen in the literature) is that left rules actually involve a variable substitution. So we come up with the following rule:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;f&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext&gt;-L&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, x : A, y : B \vdash M : C}{\Gamma, p : A \times B \vdash M[x := \mathsf{fst}\, p, y := \mathsf{snd}\, p] : C}\;\times\text{-L} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4522em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot;&gt;fst&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot;&gt;snd&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And with this rule, it becomes (I think) more obvious why natural deduction is preferred over sequent calculus, as implementing this rule in a type checker seems significantly harder. Checking the rules of natural deduction involves examining some outer-most structure of the term, and then checking the constituents of the term, possibly in an augmented context, and which rule we're dealing with is always syntax directed. But this left rule has no syntactic correspondent, so it seems as though we must nondeterministically try all left rules at each step, which is unlikely to result in a good algorithm. This is the same kind of problem that plagues extensional type theory, and ultimately results in only &lt;em&gt;derivations&lt;/em&gt; being checkable, not terms.&lt;/p&gt;
&lt;h2 id=&quot;the-type-class-connection&quot;&gt;The Type Class Connection&lt;/h2&gt;
&lt;p&gt;However, there are certain problems that I believe are well modeled by such a sequent calculus, and one of them is type class checking and associated dictionary translations. This is due mainly to the fact that the process is mainly context-directed term building, rather than term-directed type checking. As far as the type class algorithm goes, there are two interesting cases, having to do with the following two varieties of declaration:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ...
&lt;span class=&quot;hljs-class&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out that each of these leads to a left rule in a kind of type class sequent calculus:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;O&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;Eq-pre-Ord&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, \mathbf{Eq} \, a \vdash M : T}{\Gamma, \mathbf{Ord} \,  a \vdash M : T}\;\text{Eq-pre-Ord} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4133em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Ord&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Eq-pre-Ord&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;Eq-pair&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, \mathbf{Eq} \, (a, b) \vdash M : T}{\Gamma, \mathbf{Eq} \, a, \mathbf{Eq} \, b \vdash M : T}\;\text{Eq-pair} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4911em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.01em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.485em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Eq-pair&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;if &lt;code&gt;Eq a&lt;/code&gt; is a sufficient constraint for &lt;code&gt;M : T&lt;/code&gt;, then the stronger constraint &lt;code&gt;Ord a&lt;/code&gt; is also sufficient, so we can discharge the &lt;code&gt;Eq a&lt;/code&gt; constraint and use &lt;code&gt;Ord a&lt;/code&gt; instead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can discharge an &lt;code&gt;Eq (a, b)&lt;/code&gt; constraint using two constraints, &lt;code&gt;Eq a, Eq b&lt;/code&gt; together with an instance telling us how to do so. This also works for instances without contexts, giving us rules like:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;w&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;Show-Int&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{\Gamma, \mathbf{Show\, Int} \vdash M : T}{\Gamma \vdash M : T}\;\text{Show-Int} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2772em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot; style=&quot;margin-right:0.016em;&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Show-Int&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Importantly, the type inference algorithm for type classes specifies when we should use these rules based only on the contexts we're dealing with. Now, these look more like the logical sequent rules, but it turns out that they have corresponding type theory-like versions when we consider dictionary passing:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;O&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;q&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;O&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;P&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;Eq-pre-Ord&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma, eqd : \mathbf{Eq} \, a \vdash M : T}{\Gamma, ordd : \mathbf{Ord} \,  a \vdash M[eqd := \mathsf{eqOrdPrj}\, ordd] : T}\;\text{Eq-pre-Ord} &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.4522em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;dd&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Ord&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot;&gt;eqOrdPrj&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;dd&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Eq-pre-Ord&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;q&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;P&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;sans-serif&quot;&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;Eq-pair&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\frac{\Gamma, peq : \mathbf{Eq} \, (a, b) \vdash M : T}{\Gamma, aeq : \mathbf{Eq} \, a, beq : \mathbf{Eq} \, b \vdash M[peq := \mathsf{eqPair} \, aeq \, beq] : T}\;\text{Eq-pair}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.53em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.01em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathsf mtight&quot; style=&quot;margin-right:0.0139em;&quot;&gt;eqPair&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.485em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;Eq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:0.1952em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Eq-pair&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And this kind of substituting into dictionary variables produces exactly the evidence passing translation we want.&lt;/p&gt;
&lt;p&gt;Another way to look at the difference in feasibility is that type checking involves moving bottom-to-top across the rules; in natural deduction, this is always easy, and we need look only at the terms to figure out which we should do. Type class checking and dictionary translation moves from top-to-bottom, directed by the left hand context, and produces terms on the right via complex operations, and that is a perfect fit for the sequent calculus rules.&lt;/p&gt;
&lt;p&gt;I believe this corresponds to the general opinion on those who have studied sequent calculi with regard to type theory. A quick search revealed mostly papers on proof search, rather than type checking, and type classes rather fall into that realm (they're a very limited form of proof search).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/natural-deduction-sequent-calculus-and-type-classes/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Unnatural Transformations and Quantifiers</title><link>https://comonad.com/reader/2012/unnatural-transformations-and-quantifiers/</link><guid isPermaLink="false">https://comonad.com/reader/2012/unnatural-transformations-and-quantifiers/</guid><pubDate>Sat, 22 Sep 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Dan Doel · 22 September 2012&lt;/p&gt;&lt;span id=&quot;more-660&quot;&gt;&lt;/span&gt;&lt;p&gt;Recently, a fellow in category land &lt;a href=&quot;http://golem.ph.utexas.edu/category/2012/09/where_do_monads_come_from.html&quot;&gt;discovered&lt;/a&gt; a fact that we in Haskell land have actually known for a while (in addition to things most of us probably don't). Specifically, given two categories &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, a functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G : \mathcal{C} \rightarrow \mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and provided some conditions in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; hold, there exists a monad &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T^G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, the codensity monad of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In category theory, the codensity monad is given by the rather frightening expression:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mo&gt;∫&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/msub&gt;&lt;mrow&gt;&lt;mo fence=&quot;true&quot;&gt;[&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo fence=&quot;true&quot;&gt;]&lt;/mo&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; T^G(a) = \int_r \left[\mathcal{D}(a, Gr), Gr\right] &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0913em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.1608em;vertical-align:-0.3558em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;margin-right:0.1945em;position:relative;top:-0.0006em;&quot;&gt;∫&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:-0.0544em;&quot;&gt;&lt;span style=&quot;top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3558em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;minner&quot;&gt;&lt;span class=&quot;mopen delimcenter&quot; style=&quot;top:0em;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mclose delimcenter&quot; style=&quot;top:0em;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Where the integral notation denotes an &lt;a href=&quot;https://comonad.com/reader/2008/kan-extension-iii/&quot;&gt;end&lt;/a&gt;, and the square brackets denote a &lt;a href=&quot;http://nlab.mathforge.org/nlab/show/power&quot;&gt;power&lt;/a&gt;, which allows us to take what is essentially an exponential of the objects of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; by objects of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;V&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{V}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0822em;&quot;&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is &lt;a href=&quot;http://nlab.mathforge.org/nlab/show/enriched+category&quot;&gt;enriched&lt;/a&gt; in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;V&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{V}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0822em;&quot;&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Provided the above end exists, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T^G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a monad regardless of whether &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; has an &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;adjoint&lt;/a&gt;, which is the usual way one thinks of functors (in general) giving rise to monads.&lt;/p&gt;
&lt;p&gt;It also turns out that this construction is a sort of generalization of the adjunction case. If we do have &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F \dashv G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, this gives rise to a monad &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;GF&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. But, in such a case, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;≅&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T^G \cong GF&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, so the codensity monad is the same as the monad given by the adjunction when it exists, but codensity may exist when there is no adjunction.&lt;/p&gt;
&lt;p&gt;In Haskell, this all becomes a bit simpler (to my eyes, at least). Our category &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is always &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which is enriched in itself, so powers are just function spaces. And all the functors we write will be rather like &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (objects will come from kinds we can quantify over), so ends of functors will look like &lt;code&gt;forall r. F r r&lt;/code&gt; where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msup&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathcal{C}^{op} \times \mathcal{C} \rightarrow \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Then:&lt;br&gt;
&lt;code&gt;   newtype Codensity f a = Codensity (forall r. (a -&amp;gt; f r) -&amp;gt; f r)   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As mentioned, we've known for a while that we can write a Monad instance for &lt;code&gt;Codensity f&lt;/code&gt; without caring at all about &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As for the adjunction correspondence, consider the adjunction between products and exponentials: &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; - \times S \dashv S \rightarrow - &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This gives rise to the monad &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S \rightarrow (- \times S)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, the state monad. According to the facts above, we should have that &lt;code&gt;Codensity (s -&amp;gt;)&lt;/code&gt; (excuse the sectioning) is the same as state, and if we look, we see:&lt;br&gt;
&lt;code&gt;   forall r. (a -&amp;gt; s -&amp;gt; r) -&amp;gt; s -&amp;gt; r   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;which is the continuation passing, or Church (or &lt;a href=&quot;http://comments.gmane.org/gmane.comp.lang.haskell.cafe/100508&quot;&gt;Boehm-Berarducci&lt;/a&gt;) encoding of the monad.&lt;/p&gt;
&lt;p&gt;Now, it's also well known that for any monad, we can construct an adjunction that gives rise to it. There are multiple ways to do this, but the most accessible in Haskell is probably via the Kleisli category. So, given a monad &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; on &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, there is a category &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}_M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with the same objects, but where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}_M(a, b) = \mathbf{Hask}(a, Mb)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. The identity for each object is &lt;code&gt;return&lt;/code&gt; and composition of arrows is:&lt;br&gt;
&lt;code&gt;   (f &amp;gt;=&amp;gt; g) x = f x &amp;gt;&amp;gt;= g   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Our two functors are:&lt;br&gt;
&lt;code&gt;   F a = a   F f = return . f&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;U a = M a&lt;br&gt;
U f = (&amp;gt;&amp;gt;= f)&lt;/p&gt;
&lt;p&gt;Verifying that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F \dashv U&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; requires only that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≅&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}_M(F-, =) \cong \mathbf{Hask}(-, U\!\!=)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, but this is just &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;≅&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}(-, M\!\!=) \cong \mathbf{Hask}(-, M\!\!=)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which is a triviality. Now we should have that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T^U = M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So, one of the simplest monads is reader, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(e \rightarrow)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Now, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;U&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; just takes objects in the Kleisli category (which are objects in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) and applies &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to them, so we should have &lt;code&gt;Codensity (e -&amp;gt;)&lt;/code&gt; is reader. But earlier we had &lt;code&gt;Codensity (e -&amp;gt;)&lt;/code&gt; was state. So reader is state, right?&lt;/p&gt;
&lt;p&gt;We can actually arrive at this result another way. One of the most famous pieces of category theory is the &lt;a href=&quot;http://blog.sigfpe.com/2006/11/yoneda-lemma.html&quot;&gt;Yoneda lemma&lt;/a&gt;, which states that the following correspondence holds for any functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathcal{C} \rightarrow \mathbf{Set}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mo&gt;≅&lt;/mo&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msup&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/msup&gt;&lt;mrow&gt;&lt;mo fence=&quot;true&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo fence=&quot;true&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; Fa \,\, \cong \, \mathbf{Set}^\mathcal{C}\left(C(a,-), F\right) &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.1673em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9173em;&quot;&gt;&lt;span style=&quot;top:-3.139em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;minner&quot;&gt;&lt;span class=&quot;mopen delimcenter&quot; style=&quot;top:0em;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mclose delimcenter&quot; style=&quot;top:0em;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This also works for any functor into &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and looks like:&lt;br&gt;
&lt;code&gt;   F a ~= forall r. (a -&amp;gt; r) -&amp;gt; F r   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;for &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathbf{Hask} \rightarrow \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. But we also have our functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;U : \mathbf{Hask}_M \rightarrow \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which should look more like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt; &lt;span class=&quot;hljs-type&quot;&gt;U&lt;/span&gt; a ~= &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;U&lt;/span&gt; r
&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a ~= &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, we fill in &lt;code&gt;M = (e -&amp;gt;)&lt;/code&gt; and get that reader is isomorphic to state, right? What's going on?&lt;/p&gt;
&lt;p&gt;To see, we have to take a closer look at natural transformations. Given two categories &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and functors &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F, G : \mathcal{C} \rightarrow \mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, a natural transformation &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi : F \Rightarrow G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a family of maps &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi_a : Fa \rightarrow Ga&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; such that for every &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f : a \rightarrow b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; the following diagram commutes:&lt;/p&gt;
&lt;figure class=&quot;category-diagram&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/naturality-square.svg&quot; alt=&quot;Fa, Ga, Fb, Gb; ϕₐ, Ff, Gf, ϕᵦ&quot;&gt;&lt;/figure&gt;
&lt;p&gt;The key piece is what the morphisms look like. It's well known that parametricity ensures the naturality of &lt;code&gt;t :: forall a. F a -&amp;gt; G a&lt;/code&gt; for &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F, G : \mathbf{Hask} \rightarrow \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and it also works when the source is &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}^{op}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7487em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7487em;&quot;&gt;&lt;span style=&quot;top:-3.1473em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. It should also work for a category, call it &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;∼&lt;/mo&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}^{\sim}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7041em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7041em;&quot;&gt;&lt;span style=&quot;top:-3.1473em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mrel mtight&quot;&gt;∼&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which has Haskell types as objects, but where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;∼&lt;/mo&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}^{\sim}(a, b) = \mathbf{Hask}(a, b) \times \mathbf{Hask}(b, a)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7041em;&quot;&gt;&lt;span style=&quot;top:-3.1473em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mrel mtight&quot;&gt;∼&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which is the sort of category that &lt;code&gt;newtype Endo a = Endo (a -&amp;gt; a)&lt;/code&gt; is a functor from. So we should be at liberty to say:&lt;br&gt;
&lt;code&gt;   Codensity Endo a = forall r. (a -&amp;gt; r -&amp;gt; r) -&amp;gt; r -&amp;gt; r ~= [a]   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;However, hom types for &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}_M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; are not merely made up of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; hom types on the same arguments, so naturality turns out not to be guaranteed. A functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathbf{Hask}_M \rightarrow \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; must take a Kleisli arrow &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f : b \rightarrow Mc&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to an arrow &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Ff : Fb \rightarrow Fc&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and transformations must commute with that mapping. So, if we look at our use of Yoneda, we are considering transformations &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi : \mathbf{Hask}_M(a, -) \Rightarrow U&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;figure class=&quot;category-diagram&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/representable-square.svg&quot; alt=&quot;Haskₘ(a, b), Ub, Haskₘ(a, c), Uc; ϕₐ, Haskₘ(a, f), Uf, ϕₕ&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Now, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}_M(a,b) = \mathbf{Hask}(a, Mb)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Ub = Mb&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. So&lt;/p&gt;
&lt;p&gt;&lt;code&gt;t :: forall r. (a -&amp;gt; M r) -&amp;gt; M r&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;will get us the right type of maps. But, the above commutative square corresponds to the condition that for all &lt;code&gt;f :: b -&amp;gt; M c&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;   t . (&amp;gt;=&amp;gt; f) = (&amp;gt;&amp;gt;= f) . t   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So, if we have &lt;code&gt;h :: a -&amp;gt; M b&lt;/code&gt;, Kleisli composing it with &lt;code&gt;f&lt;/code&gt; and then feeding to &lt;code&gt;t&lt;/code&gt; is the same as feeding &lt;code&gt;h&lt;/code&gt; to &lt;code&gt;t&lt;/code&gt; and then binding the result with &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, if we go back to reader, we can consider the reader morphism:&lt;br&gt;
&lt;code&gt;   f = const id :: a -&amp;gt; e -&amp;gt; e   &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For all relevant &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt;, &lt;code&gt;m &amp;gt;&amp;gt;= f = id&lt;/code&gt; and &lt;code&gt;g &amp;gt;=&amp;gt; f = f&lt;/code&gt;. So the&lt;br&gt;
naturality condition here states that &lt;code&gt;t f = id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, &lt;code&gt;t :: forall r. (a -&amp;gt; e -&amp;gt; r) -&amp;gt; e -&amp;gt; r&lt;/code&gt;. The general form of these is state actions (I've split &lt;code&gt;e -&amp;gt; (a, e)&lt;/code&gt; into two pieces):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; f e = f (v e) (st e)
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  rd :: e -&amp;gt; a
  st :: e -&amp;gt; e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;f = const id&lt;/code&gt;, then:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; (const id) e = st e
 &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
 st :: e -&amp;gt; e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But our naturality condition states that this must be the identity, so we must have &lt;code&gt;st = id&lt;/code&gt;. That is, the naturality condition selects &lt;code&gt;t&lt;/code&gt; for which the corresponding state action does not change the state, meaning it is equivalent to a reader action! Presumably the definition of an end (which involves dinaturality) enforces a similar condition, although I won't work through it, as it'd be rather more complicated.&lt;/p&gt;
&lt;p&gt;However, we have learned a lesson. Quantifiers do not necessarily enforce (di)naturality for every category with objects of the relevant kind. It is important to look at the hom types, not just the objects .In this case, the point of failure seems to be the common, extra &lt;code&gt;s&lt;/code&gt;. Even though the type contains nautral transformations for the similar functors over &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, they can (in general) still manipulate the shared parameter in ways that are not natural for the domain in question.&lt;/p&gt;
&lt;p&gt;I am unsure of how exactly one could enforce the above condition in (Haskell's) types. For instance, if we consider:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;forall r m. Monad m =&amp;gt; (a -&amp;gt; m r) -&amp;gt; m r&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This still contains transformations of the form:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;t k = k a &amp;gt;&amp;gt; k a&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And for this to be natural would require:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(k &amp;gt;=&amp;gt; f) a &amp;gt;&amp;gt; (k &amp;gt;=&amp;gt; f) a = (k a &amp;gt;&amp;gt; k a) &amp;gt;&amp;gt;= f&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which is not true for all possible instantiations of f. It seems as though leaving &lt;code&gt;m&lt;/code&gt; unconstrained would be sufficient, as all that could happen is &lt;code&gt;t&lt;/code&gt; feeding a value to &lt;code&gt;k&lt;/code&gt; and yielding the result, but it seems likely to be over-restrictive.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/unnatural-transformations-and-quantifiers/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Working around Hackage Outages</title><link>https://comonad.com/reader/2012/hackage-mirror/</link><guid isPermaLink="false">https://comonad.com/reader/2012/hackage-mirror/</guid><pubDate>Wed, 29 Aug 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 29 August 2012&lt;/p&gt;&lt;p&gt;Luite Stegeman has a mirror of the packages from &lt;a href=&quot;https://hackage.haskell.org/&quot;&gt;Hackage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;He uses it to power his incredibly useful &lt;a href=&quot;http://hdiff.luite.com/&quot;&gt;hdiff&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;During a Hackage outage, you can set up your local cabal configuration to point to it instead by (temporarily) replacing the remote-repo in your &lt;code&gt;~/.cabal/config&lt;/code&gt; file with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;remote-repo:
  hdiff.luite.com:http://hdiff.luite.com/packages/archive
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then running &lt;code&gt;cabal update&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I have a &lt;a href=&quot;https://github.com/ekmett/lens/blob/master/config&quot;&gt;&lt;code&gt;~/.cabal/config&lt;/code&gt;&lt;/a&gt; that I use whenever hackage goes down in my &lt;a href=&quot;https://github.com/ekmett/lens&quot;&gt;lens&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;If you use &lt;a href=&quot;http://travis-ci.org/&quot;&gt;travis-ci&lt;/a&gt;, you can avoid build failures during hackage outages by first copying that config to ~/.cabal/config &lt;a href=&quot;https://github.com/ekmett/lens/blob/master/.travis.yml#L4&quot;&gt;during before_install&lt;/a&gt;. -- You'll still be stuck waiting while it first tries to refresh from the real hackage server, but it only adds a few minutes to buildbot times.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/hackage-mirror/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Making de Bruijn Succ Less</title><link>https://comonad.com/reader/talks/bound-slides-2012/</link><guid isPermaLink="false">https://comonad.com/reader/talks/bound-slides-2012/</guid><pubDate>Thu, 26 Jul 2012 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 26 July 2012 · slides published&lt;/p&gt;&lt;p&gt;A presentation on variable binding, de Bruijn indices, and the approach used by the bound library.&lt;/p&gt;&lt;p&gt;Related article: &lt;a href=&quot;https://comonad.com/reader/2015/bound/&quot;&gt;Bound&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/bound-slides-2012/&quot;&gt;Read the slides&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Mirrored Lenses</title><link>https://comonad.com/reader/2012/mirrored-lenses/</link><guid isPermaLink="false">https://comonad.com/reader/2012/mirrored-lenses/</guid><pubDate>Sun, 24 Jun 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 24 June 2012&lt;/p&gt;&lt;span id=&quot;more-600&quot;&gt;&lt;/span&gt;&lt;p&gt;Lenses are a great way to deal with functional references, but there are two common issues that arise from their use.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is a long-standing folklore position that lenses do not support polymorphic updates. This has actually caused a fair bit of embarrassment for the folks who'd like to incorporate lenses in any Haskell record system improvement.&lt;/li&gt;
&lt;li&gt;Access control. It'd be nice to have read-only or write-only properties -- &quot;one-way&quot; or &quot;mirrored&quot; lenses, as it were. Moreover, lenses are commonly viewed as an all or nothing proposition, in that it is hard to mix them with arbitrary user functions.&lt;/li&gt;
&lt;li&gt;Finally there is a bit of a cult around trying to generalize lenses by smashing a monad in the middle of them somewhere, it would be nice to be able to get into a list and work with each individual element in it without worrying about someone mucking up our lens laws, and perhaps avoid the whole generalized lens issue entirely.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We'll take a whack at each of these concerns in turn today.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;   &lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE Rank2Types #-}&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;-- we'll relax this later&lt;/span&gt;
   &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Complex &lt;span class=&quot;hljs-comment&quot;&gt;-- for complex examples&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, let us consider the type of van Laarhoven lenses:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lens&lt;/span&gt; a b =&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
  (b -&amp;gt; f b) -&amp;gt; a -&amp;gt; f a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with a couple of examples:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;realLens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lens&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;realLens&lt;/span&gt; f (r :+ i) = fmap (:+ i) (f r)

&lt;span class=&quot;hljs-title&quot;&gt;imagLens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lens&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;imagLens&lt;/span&gt; f (r :+ i) = fmap (r :+) (f i)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These lenses have some very nice properties that we're going to exploit. By far their nicest property is that you can compose them using just &lt;code&gt;(.)&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; from the &lt;code&gt;Prelude&lt;/code&gt; rather than having to go off and write a &lt;code&gt;Category&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lens-families&quot;&gt;Lens Families&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://r6.ca/blog/20120623T104901Z.html&quot;&gt;Russell O'Connor recently noted that these lenses permit polymorphic update&lt;/a&gt; if you simply generalize their type signature to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d =&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
  (c -&amp;gt; f d) -&amp;gt; a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'd like to note that you can't just let these 4 arguments vary with complete impunity, so I'll be referring to these as &quot;lens families&quot; rather than polymorphic lenses, a point that I'll address further below. In short, we want the original lens laws to still hold in spite of the generalized type signature, and this forces some of these types to be related.&lt;/p&gt;
&lt;p&gt;As an aside, each of the other lens types admit this same generalization! For instance the &lt;code&gt;Lens&lt;/code&gt; type in &lt;a href=&quot;https://hackage.haskell.org/package/data-lens&quot;&gt;data-lens&lt;/a&gt; can be generalized using an indexed store comonad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; c d b = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) c&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; g c) = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (f . g) c

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; a b c d = &lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can freely convert back and forth to van Laarhoven lens families:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;dlens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;dlens&lt;/span&gt; l = &lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; (l (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; id))

&lt;span class=&quot;hljs-title&quot;&gt;plens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; a b c d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;plens&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;DataLensFamily&lt;/span&gt; l) f a = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; l a &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; g c -&amp;gt; fmap g (f c)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I leave it as an exercise to the reader to generalize the other lens types, but we'll stick to van Laarhoven lens families almost exclusively below.&lt;/p&gt;
&lt;p&gt;As Russell noted, we can define functions to get, modify and set the target of a lens very easily. I'll create local names for &lt;code&gt;Identity&lt;/code&gt; and &lt;code&gt;Const&lt;/code&gt;, mostly to help give nicer error messages later.&lt;/p&gt;
&lt;p&gt;We can read from a lens family:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; ^.
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; b a = &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;got&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap _ (&lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; b
(^.) :: a -&amp;gt; ((c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; c d) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; c b) -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; ^. l = got (l &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can modify the target of the lens:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unsetting&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; (f a)
&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; %=
(%=) :: ((c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b) -&amp;gt; (c -&amp;gt; d) -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;l&lt;/span&gt; %= f = unsetting . l (&lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can set the target of the lens with impunity:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; ^=
(^=) :: ((c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b) -&amp;gt; d -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;l&lt;/span&gt; ^= v = l %= const v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can build a lens family from a getter/setter pair&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lens&lt;/span&gt; :: (a -&amp;gt; c) -&amp;gt; (a -&amp;gt; d -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;lens&lt;/span&gt; f g h a = fmap (g a) (h (f a))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or from a family of isomorphisms:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;iso&lt;/span&gt; :: (a -&amp;gt; c) -&amp;gt; (d -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;iso&lt;/span&gt; f g h a = fmap g (h (f a))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With these combinators in hand, we need some actual lens families to play with. Fortunately they are just as easy to construct as simple lenses. The only thing that changes is the type signature.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fstLens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; (a,c) (b,c) a b
&lt;span class=&quot;hljs-title&quot;&gt;fstLens&lt;/span&gt; f (a,b) = fmap (\x -&amp;gt; (x,b)) (f a)

&lt;span class=&quot;hljs-title&quot;&gt;sndLens&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; (a,b) (a,c) b c
&lt;span class=&quot;hljs-title&quot;&gt;sndLens&lt;/span&gt; f (a,b) = fmap ((,) a) (f b)

&lt;span class=&quot;hljs-title&quot;&gt;swap&lt;/span&gt; :: (a,b) -&amp;gt; (b,a)
&lt;span class=&quot;hljs-title&quot;&gt;swap&lt;/span&gt; (a,b) = (b,a)

&lt;span class=&quot;hljs-title&quot;&gt;swapped&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; (a,b) (c,d) (b,a) (d,c)
&lt;span class=&quot;hljs-title&quot;&gt;swapped&lt;/span&gt; = iso swap swap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These can also build 'traditional' lenses:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;negated&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lens&lt;/span&gt; a a
&lt;span class=&quot;hljs-title&quot;&gt;negated&lt;/span&gt; = iso negate negate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And since &lt;code&gt;Lens&lt;/code&gt; and &lt;code&gt;LensFamily&lt;/code&gt; are both type aliases, we can freely mix and match lenses with lens families:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;) ^.fstLens.realLens
&lt;span class=&quot;hljs-number&quot;&gt;1.0&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; fstLens . realLens ^= &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; $ (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
(&lt;span class=&quot;hljs-number&quot;&gt;4.0&lt;/span&gt; :+ &lt;span class=&quot;hljs-number&quot;&gt;2.0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, we can now change types with our lens updates!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; (fstLens . sndLens ^= &lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;) ((&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,()),&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
((&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;),&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can even do things like use the combinator&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;traverseLens&lt;/span&gt; :: ((c -&amp;gt; c) -&amp;gt; a -&amp;gt; b) -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;traverseLens&lt;/span&gt; f = f id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to project a &lt;code&gt;Functor&lt;/code&gt; out through an appropriate lens family:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; :t traverseLens (fstLens . sndLens)
&lt;span class=&quot;hljs-title&quot;&gt;traverseLens&lt;/span&gt; (fstLens . sndLens)
  :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; ((a, f b), c) -&amp;gt; f ((a, b), c)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That takes care of polymorphic updates.&lt;/p&gt;
&lt;h2 id=&quot;why-is-it-a-lens-family&quot;&gt;Why is it a Lens Family?&lt;/h2&gt;
&lt;p&gt;So, why do I use the term &quot;lens family&quot; rather than &quot;polymorphic lens&quot;?&lt;/p&gt;
&lt;p&gt;In order for the lens laws to hold, the 4 types parameterizing our lens family must be interrelated.&lt;/p&gt;
&lt;p&gt;In particular you need to be able to put back (with &lt;code&gt;^=&lt;/code&gt;) what you get out of the lens (with &lt;code&gt;^.&lt;/code&gt;) and put multiple times.&lt;/p&gt;
&lt;p&gt;This effectively constrains the space of possible legal lens families to those where there exists an index kind &lt;code&gt;i&lt;/code&gt;, and two type families &lt;code&gt;outer :: i -&amp;gt; *&lt;/code&gt;, and &lt;code&gt;inner :: i -&amp;gt; *&lt;/code&gt;. If this were a viable type signature, then each lens family would actually have 2 parameters, yielding something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- pseudo-Haskell&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- type LensFamily outer inner =&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--    forall a b. LensFamily (outer a) (outer b) (inner a) (inner b)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but you can't pass in type families as arguments like that, and even if you could, their lack of injectivity doesn't give the type checker enough to work with to compose your lenses. By specifying all 4 type arguments independently, we give the compiler enough to work with. But since the arguments aren't just freely polymorphic and are instead related by these index types, I'm choosing to call them &quot;lens families&quot; rather than &quot;polymorphic lenses&quot;.&lt;/p&gt;
&lt;h2 id=&quot;getters&quot;&gt;Getters&lt;/h2&gt;
&lt;p&gt;Note, we didn't use the full polymorphism of the van Laarhoven lenses in the signatures of &lt;code&gt;(^.)&lt;/code&gt;, &lt;code&gt;(%=)&lt;/code&gt; and &lt;code&gt;(^=)&lt;/code&gt; above.&lt;/p&gt;
&lt;p&gt;What happens when we restrict the type of &lt;code&gt;Functor&lt;/code&gt; we're allowed to pass to our lens?&lt;/p&gt;
&lt;p&gt;If we generalize the type of our getter ever so slightly from the type we pass to &lt;code&gt;(^.)&lt;/code&gt; to permit composition, we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; a c = forall r d b. (&lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; r b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can make getters out of arbitrary Haskell functions that we have lying around with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | build a getting out of a function&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;getting&lt;/span&gt; :: (a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; a b
&lt;span class=&quot;hljs-title&quot;&gt;getting&lt;/span&gt; g f = &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; . got . f . g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;getFst&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; (a,b) a
&lt;span class=&quot;hljs-title&quot;&gt;getFst&lt;/span&gt; = getting fst

&lt;span class=&quot;hljs-title&quot;&gt;getSnd&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; (a,b) b
&lt;span class=&quot;hljs-title&quot;&gt;getSnd&lt;/span&gt; = getting snd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is particularly nice for things that &lt;em&gt;can't&lt;/em&gt; be made into real lenses or lens families, because of loss of information:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;getPhase&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; a) a
&lt;span class=&quot;hljs-title&quot;&gt;getPhase&lt;/span&gt; = getting phase

&lt;span class=&quot;hljs-title&quot;&gt;getAbs&lt;/span&gt;, getSignum  :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getter&lt;/span&gt; a a
&lt;span class=&quot;hljs-title&quot;&gt;getAbs&lt;/span&gt; = getting abs
&lt;span class=&quot;hljs-title&quot;&gt;getSignum&lt;/span&gt; = getting signum
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notably, &lt;code&gt;getMagnitude&lt;/code&gt; and &lt;code&gt;getPhase&lt;/code&gt; can't be legal lenses because when the &lt;code&gt;magnitude&lt;/code&gt; is 0, you lose &lt;code&gt;phase&lt;/code&gt; information.&lt;/p&gt;
&lt;p&gt;These can be mixed and matched with other lenses when dereferencing with &lt;code&gt;(^.)&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)) ^. getting snd . fstLens . getting magnitude
&lt;span class=&quot;hljs-number&quot;&gt;2.23606797749979&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we get a type error when we attempt to write to a &lt;code&gt;Getter&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; getting magnitude ^= &lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;
&amp;lt;interactive&amp;gt;:&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
    &lt;span class=&quot;hljs-type&quot;&gt;Couldn't&lt;/span&gt; match expected &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d0'&lt;/span&gt;
                with actual &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; r0 d1'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Expected&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;c0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt;) -&amp;gt; a1 -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b1&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Actual&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;c0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r0&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d1&lt;/span&gt;) -&amp;gt; a0 -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; r0 b0&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the return &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; of a call of `getting'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the first argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(^=)', namely `getting magnitude'
&amp;lt;/interactive&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;setters&quot;&gt;Setters&lt;/h2&gt;
&lt;p&gt;So what about write-only properties?&lt;/p&gt;
&lt;p&gt;These have a less satisfying solution. We have to break our lens family structure slightly to make something that can strictly &lt;em&gt;only&lt;/em&gt; be written to, by disabling the ability to read our current value entirely.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Setter&lt;/span&gt; a d b = (() -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;setting&lt;/span&gt; :: (a -&amp;gt; d -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setter&lt;/span&gt; a d b
&lt;span class=&quot;hljs-title&quot;&gt;setting&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; (f a (unsetting (g ())))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can make setters out of functions that take two arguments:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;plus&lt;/span&gt;, times :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setter&lt;/span&gt; a a a
&lt;span class=&quot;hljs-title&quot;&gt;plus&lt;/span&gt; = setting (+)
&lt;span class=&quot;hljs-title&quot;&gt;times&lt;/span&gt; = setting (*)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; setting (+) ^= &lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt; $ &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;44&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; fstLens . setting (*) ^= &lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt; $ (&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
(&lt;span class=&quot;hljs-number&quot;&gt;24&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, these lenses have the unsatisfying property that they can only be placed last in the chain of lenses we're setting.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; (setting (+) . realLens ^= &lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&amp;lt;interactive&amp;gt;:&lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;:
    &lt;span class=&quot;hljs-type&quot;&gt;Couldn't&lt;/span&gt; match expected &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `()' with actual &lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; d0'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Expected&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt;) -&amp;gt; () -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b0&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Actual&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt;)&lt;/span&gt;
                   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; d0 -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; d0)
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the second argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(.)', namely `realLens'
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the first argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(^=)', namely `setting (+) . realLens'
&amp;lt;/interactive&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This isn't surprising, if you consider that to compose &lt;code&gt;data-lens&lt;/code&gt; lenses you need to use &lt;code&gt;%=&lt;/code&gt; to chain setters.&lt;/p&gt;
&lt;h2 id=&quot;modifiers&quot;&gt;Modifiers&lt;/h2&gt;
&lt;p&gt;So what do we need to do to make a lens we can only modify but not read?&lt;/p&gt;
&lt;p&gt;Lets restore the lens family structure!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Modifier&lt;/span&gt; a b c d = (&lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;modifying&lt;/span&gt; :: ((c -&amp;gt; d) -&amp;gt; a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Modifier&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;modifying&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; (f (unsetting . g) a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;modifying&lt;/code&gt; makes a modify-only lens family you can modify using local information, but can't tell anyone about the contents of.&lt;/p&gt;
&lt;p&gt;This lets us work with a lens over a variable number of elements in a structure, without worrying about a user accidentally &quot;putting back&quot; too many or too few entries.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; modifying map %= (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) $ [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]
[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;They can be composed with other lenses:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; modifying map . sndLens %= (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) $ [(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)]
[(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and unlike with a &lt;code&gt;Setter&lt;/code&gt;, you can compose a &lt;code&gt;Modifier&lt;/code&gt; with a &lt;code&gt;Modifier&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;modifying&lt;/span&gt; fmap . modifying fmap
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; g, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f) =&amp;gt;
     (c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d) -&amp;gt; f (g c) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; (f (g d))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but they cannot be read from directly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;] ^. modifying fmap
&amp;lt;interactive&amp;gt;:&lt;span class=&quot;hljs-number&quot;&gt;18&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;:
    &lt;span class=&quot;hljs-type&quot;&gt;Couldn't&lt;/span&gt; match expected &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; c0 d0'&lt;/span&gt;
                with actual &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d1'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Expected&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;c0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c0&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt;) -&amp;gt; [t0] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; c0 b1&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Actual&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: &lt;span class=&quot;hljs-type&quot;&gt;Modifier&lt;/span&gt; a0 b0 c0 d1&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the return &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; of a call of `modifying'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the second argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(^.)', namely `modifying map'
&amp;lt;/interactive&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can map over restricted domains:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;reals&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; b) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Modifier&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; b) a b
&lt;span class=&quot;hljs-title&quot;&gt;reals&lt;/span&gt; = modifying (\f (r :+ i) -&amp;gt; f r :+ f i)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and everything still composes:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; reals %= (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) $  &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :+ &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; :+ &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; fstLens . reals %= (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) $ (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; :+ &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;)
(&lt;span class=&quot;hljs-number&quot;&gt;2.0&lt;/span&gt; :+ &lt;span class=&quot;hljs-number&quot;&gt;3.0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These aren't limited to actions that map over the entire structure, however!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; :m + &lt;span class=&quot;hljs-type&quot;&gt;Data&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Lens&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; modifying (`adjust` &lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;) %= (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) $
      fromList [(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)]
&lt;span class=&quot;hljs-title&quot;&gt;fromList&lt;/span&gt; [(&lt;span class=&quot;hljs-string&quot;&gt;&quot;goodbye&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;hljs-string&quot;&gt;&quot;hello&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This lets us update potentially nested structures where something may or may not be present , which was fairly tedious to do with earlier lens representations.&lt;/p&gt;
&lt;p&gt;Both the former map-like example and the latter update-like behavior were commonly used examples in calls for partial lenses or 'multi-lenses', but here they are able to implemented using a restricted form of a more traditional lens type, and moreover they compose cleanly with other lenses and lens families.&lt;/p&gt;
&lt;h2 id=&quot;rank-1-lens-families&quot;&gt;Rank-1 Lens Families&lt;/h2&gt;
&lt;p&gt;At the very start I mentioned that you can dispense with the need for Rank-2 Types. Doing so requires much more tedious type signatures as the &lt;code&gt;LensFamily&lt;/code&gt;, &lt;code&gt;Getter&lt;/code&gt;, &lt;code&gt;Setter&lt;/code&gt; and &lt;code&gt;Lens&lt;/code&gt; aliases are no longer legal. Also, if you want to take a lens as an argument and use it in multiple contexts (e.g. as both a getter and a setter), you'll need to clone it to obtain a lens family. For example, this fails:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; :t \l y -&amp;gt; l ^= y ^. l + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; $ y
&amp;lt;interactive&amp;gt;:&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:&lt;span class=&quot;hljs-number&quot;&gt;19&lt;/span&gt;:
    &lt;span class=&quot;hljs-type&quot;&gt;Couldn't&lt;/span&gt; match expected &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; d0 d1'&lt;/span&gt;
                with actual &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; d0'&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Expected&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d1&lt;/span&gt;) -&amp;gt; a1 -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Getting&lt;/span&gt; d0 b1&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Actual&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt;: (&lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d0&lt;/span&gt;) -&amp;gt; a0 -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Setting&lt;/span&gt; b0&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the second argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(^.)', namely `l'
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; the first argument &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; `(+)', namely `y ^. l'
&amp;lt;/interactive&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we can clone the supplied monomorphic lens using the composition of &lt;code&gt;dlens&lt;/code&gt; and &lt;code&gt;plens&lt;/code&gt; above, since the &lt;code&gt;DataLensFamily&lt;/code&gt; completely characterizes the &lt;code&gt;LensFamily&lt;/code&gt; with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;clone&lt;/span&gt; ::
  ((c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; c d d) -&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; c d b)) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LensFamily&lt;/span&gt; a b c d
&lt;span class=&quot;hljs-title&quot;&gt;clone&lt;/span&gt; l f a = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; l (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; id) a &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; g c -&amp;gt; fmap g (f c)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then the following code type checks:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ghci&lt;/span&gt;&amp;gt; :t \l y -&amp;gt; clone l ^= y ^. clone l + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; $ y
\l y -&amp;gt; clone l ^= y ^. clone l + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; $ y
  :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; d =&amp;gt; ((c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; c d1 d1) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; d d b) -&amp;gt; a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means you could implement an entire library to deal with lens families with restricted getters and setters and remain within the confines of Haskell 98. However, the type signatures are considerably less elegant than what becomes available when you simply add Rank2Types.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So, we've demonstrated that van Laarhoven lens families let you have lenses that permit polymorphic update, let you offer lenses that are restricted to only allowing the use of getters, setters or modifiers, while granting you easy composition with the existing &lt;code&gt;(.)&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; from the &lt;code&gt;Prelude&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I think the practical existence and power of these combinators make a strong case for their use in any serious record reform proposal.&lt;/p&gt;
&lt;p&gt;My thanks go to Russell O'Connor. He first noticed that you can generalize van Laarhoven lenses and proposed the &lt;code&gt;clone&lt;/code&gt; combinator as a path to Haskell 98/2010 compatibility, while retaining the nicer composition model.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/mirrored-lenses/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Where’s Waldo?</title><link>https://comonad.com/reader/2012/wheres-waldo/</link><guid isPermaLink="false">https://comonad.com/reader/2012/wheres-waldo/</guid><pubDate>Sun, 10 Jun 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 10 June 2012&lt;/p&gt;&lt;p&gt;No, I don't mean like &lt;a href=&quot;http://www.optipess.com/2012/05/28/lost-and-found/&quot;&gt;this&lt;/a&gt;, but rather, If you spent any time trying to figure out xkcd's &lt;a href=&quot;http://xkcd.com/1037/&quot;&gt;Umwelt&lt;/a&gt; April Fool comic this year, you may be interested in the Haskell source code. They used all sorts of information about you, the browser you were using, the resolution of your screen, to the geocoding of the network address you came from, etc. to serve up a custom web comic.&lt;/p&gt;
&lt;p&gt;Today, davean posted to github the code for &lt;a href=&quot;https://github.com/davean/waldo&quot;&gt;waldo&lt;/a&gt;, the engine he wrote to drive that comic.&lt;/p&gt;
&lt;p&gt;Alas, he was not kind enough to actually supply the code for the umwelt comic strip itself, so you'll still be left wondering if the internet managed to find all of the Easter eggs. (Are they still Easter eggs when you release something a week before Easter?) You may find the list of links below useful if you want to get a feel for the different responses it gave people.&lt;/p&gt;
&lt;p&gt;[ &lt;a href=&quot;http://www.webpronews.com/xkcd-wins-april-fools-day-with-amazing-changing-comic-gag-2012-04&quot;&gt;Article&lt;/a&gt; | &lt;a href=&quot;http://forums.xkcd.com/viewtopic.php?t=82442&quot;&gt;xkcd's Forum&lt;/a&gt; | &lt;a href=&quot;http://news.ycombinator.com/item?id=3784216&quot;&gt;Hacker News&lt;/a&gt; | &lt;a href=&quot;http://www.reddit.com/r/haskell/comments/roa2k/xkcds_april_1st_joke_this_year_was_written_in/&quot;&gt;/r/haskell&lt;/a&gt; ]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[Update: Jun 10, 9:09pm]&lt;/strong&gt; davean just posted a &lt;a href=&quot;http://www.reddit.com/r/haskell/comments/uved7/waldo_the_haskell_powered_codebase_behind_xkcds/&quot;&gt;rather insightful post mortem&lt;/a&gt; of the development of waldo that talks a bit about why xkcd uses Haskell internally.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/wheres-waldo/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Purely Functional Data Structures for On-Line LCA</title><link>https://comonad.com/reader/talks/kmett-2012-online-lca/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2012-online-lca/</guid><pubDate>Thu, 31 May 2012 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 31 May 2012 · slides published&lt;/p&gt;&lt;p&gt;Slides on skew-binary representations and online lowest-common-ancestor search.&lt;/p&gt;&lt;p&gt;Related article: &lt;a href=&quot;https://comonad.com/reader/2015/online-lca/&quot;&gt;On-line Lowest Common Ancestor&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2012-online-lca/&quot;&gt;Read the slides&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Catamorphism Knol</title><link>https://comonad.com/reader/2012/catamorphism-knol/</link><guid isPermaLink="false">https://comonad.com/reader/2012/catamorphism-knol/</guid><pubDate>Sun, 27 May 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 27 May 2012&lt;/p&gt;&lt;p&gt;I was contacted by someone who wanted to read my old catamorphism knol, despite the fact that Google Knol is no more.&lt;/p&gt;
&lt;p&gt;Fortunately, while it was rather inconvenient that they shut down Google Knol completely, and I'll forever remember a knol as a &quot;unit of abandonment&quot;, Google did provide a nice way to download at least your own user content and for that I am grateful.&lt;/p&gt;
&lt;p&gt;I have fixed up the internal linkage as much as possible and have placed a copy of the original article below.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/catamorphisms.html&quot;&gt;Catamorphisms: A Knol&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sadly, as I am not &quot;Dark Magus&quot;, I am unable to download the Russian translation. If anyone knows how to contact him, I would love to obtain and preserve a copy of the translation as well.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/catamorphism-knol/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Wadler’s Law Revisited</title><link>https://comonad.com/reader/2012/wadlers-law-revisited/</link><guid isPermaLink="false">https://comonad.com/reader/2012/wadlers-law-revisited/</guid><pubDate>Mon, 02 Apr 2012 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 2 April 2012&lt;/p&gt;&lt;span id=&quot;more-571&quot;&gt;&lt;/span&gt;&lt;p&gt;In light of the burgeoning length of the ongoing record discussion &lt;a href=&quot;http://www.haskell.org/pipermail/glasgow-haskell-users/2011-October/021101.html&quot;&gt;sparked off by Simon Peyton-Jones in October&lt;/a&gt;, I would like to propose that we recognize an extension to Wadler's law (supplied in bold), which I'll refer to as the &quot;Weak Record Conjecture&quot; below.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In any language design, the total time spent discussing a feature in this list is proportional to two raised to the power of its position.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0. Semantics&lt;/li&gt;
&lt;li&gt;1. Syntax&lt;/li&gt;
&lt;li&gt;2. Lexical syntax&lt;/li&gt;
&lt;li&gt;3. Lexical syntax of comments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4. Semantics of records&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;I base the Weak Record Conjecture on the stable of proposed record semantics, which now includes (among others) &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields&quot;&gt;Simple Overloaded Record Fields (SORF)&lt;/a&gt;, &lt;a href=&quot;http://www.youtube.com/watch?v=pEig1D4sJdI%3C/a%3E,%20%20%3C/a%3E%3Ca%20href=&quot;&gt;Agda-derived Records (ADR)&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/wiki/Records/NameSpacing&quot;&gt;Frege-derived Records (FDR)&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/wiki/Records/TypePunningDeclaredOverloadedRecordFields&quot;&gt;Type-Punning Declared Overloaded Record Fields (TPDORF)&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/wiki/Records/SyntaxDirectedNameResolution&quot;&gt;Syntax Directed Name Resolution&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/wiki/Records/TypeIndexedRecords&quot;&gt;Type Indexed Records&lt;/a&gt; and the less seriously proposed &lt;a href=&quot;http://www.haskell.org/pipermail/glasgow-haskell-users/2012-April/022219.html&quot;&gt;Homotopy Extensional Record Proposal (HERP)&lt;/a&gt; and &lt;a href=&quot;http://www.haskell.org/pipermail/glasgow-haskell-users/2012-April/022219.html&quot;&gt;Dependent Extensional Record Proposal (DERP)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is an additional option implied but not stated in all of this, which is the option to &quot;Leave Well Enough Alone&quot; (LWEA?), since you can always &lt;a href=&quot;http://stackoverflow.com/questions/5767129/lenses-fclabels-data-accessor-which-library-for-structure-access-and-mutatio/5769285#5769285&quot;&gt;Man Up and Learn Lenses (MUALL)&lt;/a&gt;. Given that every record proposal I've seen thus far breaks polymorphic field updates to some degree, and lenses are going to be compatible with whatever mess folks settle on, even preserving the status quo, this is the path I've chosen to take.&lt;/p&gt;
&lt;p&gt;Now, based on the fact that discussions of &lt;a href=&quot;http://www.haskell.org/pipermail/glasgow-haskell-users/2012-January/021531.html&quot;&gt;syntax have already started&lt;/a&gt;, and the intuition supplied by the ordering already present in Wadler's insightful law, I would also like to conjecture that perhaps an even stronger version of Wadler's law might be able to be stated, the &quot;Strong Record Conjecture&quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In any language design, the total time spent discussing a feature in this list is proportional to two raised to the power of its position.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;0. Semantics&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1. Syntax&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2. Lexical syntax&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3. Lexical syntax of comments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;4. Semantics of records&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5. Syntax of records&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;6. Lexical syntax of records&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Under the Strong Record Conjecture, even in the unlikely event that universal accord could be reached on record semantics today — 164 days into this discussion — we'd still be due for at least another 3 years (328 + 656 days) of backlogged complaining over the syntax before anything gets done.&lt;/p&gt;
&lt;p&gt;The evidence thus far is pretty strong that at least the Weak Record Conjecture holds — if anything the exponent is too small and may require further calibration, but we don't have much data yet on the Strong Record Conjecture. Consequently, and in the name of science, I plan to check in again on the record debate in 3 years. Hopefully by then we will have resolved the remaining semantic issues, and will have a better feel for the necessary time commitment required to resolve items 5 and 6.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2012/wadlers-law-revisited/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Searching Infinity Parametrically</title><link>https://comonad.com/reader/2011/searching-infinity/</link><guid isPermaLink="false">https://comonad.com/reader/2011/searching-infinity/</guid><pubDate>Sun, 25 Dec 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 December 2011&lt;/p&gt;&lt;span id=&quot;more-510&quot;&gt;&lt;/span&gt;&lt;p&gt;Andrej Bauer recently gave a really nice talk on how you can exploit side-effects to make a faster version of Martin Escardo's pseudo-paradoxical combinators.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://math.andrej.com/2011/12/06/how-to-make-the-impossible-functionals-run-even-faster/&quot;&gt;A video of his talk is available over on his blog&lt;/a&gt;, and his presentation is remarkably clear, and would serve as a good preamble to the code I'm going to present below.&lt;/p&gt;
&lt;p&gt;Andrej gave a related invited talk back at &lt;a href=&quot;http://msfp.org.uk/&quot;&gt;MSFP 2008&lt;/a&gt; in Iceland, and afterwards over lunch I cornered him (with Dan Piponi) and explained how you could use parametricity to close over the side-effects of monads (or arrows, etc) but I think that trick was lost in the chaos of the weekend, so I've chosen to resurrect it here, and improve it to handle some of his more recent performance enhancements, and show that you don't need side-effects to speed up the search after all!&lt;/p&gt;
&lt;p&gt;First, we'll need to import a few things:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Maybe (&lt;span class=&quot;hljs-title&quot;&gt;fromMaybe&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.IntMap (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Data.IntMap &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; IntMap
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Trans.Class
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor.Identity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What are looking for is an implementation of &lt;a href=&quot;http://en.wikipedia.org/wiki/Epsilon_calculus&quot;&gt;Hilbert's epsilon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is a formal mechanism for eliminating existentials over some non-empty set &lt;strong&gt;X&lt;/strong&gt; by defining a function&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;ε: (&lt;span class=&quot;hljs-type&quot;&gt;X&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Prop&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;X&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;such that if there exists an &lt;em&gt;x&lt;/em&gt; in &lt;strong&gt;X&lt;/strong&gt; such that &lt;em&gt;p&lt;/em&gt;(&lt;strong&gt;X&lt;/strong&gt;) holds then &lt;em&gt;p&lt;/em&gt;(&lt;em&gt;ε&lt;/em&gt;(&lt;em&gt;p&lt;/em&gt;)) holds.&lt;/p&gt;
&lt;p&gt;As noted by Andrej, we could reify this constructively as a function &quot;epsilon :: (X -&amp;gt; Bool) -&amp;gt; X&quot; for some X.&lt;/p&gt;
&lt;p&gt;Now, for some sets, Hilbert's epsilon is really easy to define. If X is a finite set, you can just exhaustively enumerate all of the options returning a member of X such that the property holds if any of them do, otherwise since X is non-empty, just return one of the elements that you tested.&lt;/p&gt;
&lt;p&gt;This would be a pretty boring article and I'd be back to eating Christmas dinner with my family if that was all there was to it. However, certain infinite spaces can also be searched.&lt;/p&gt;
&lt;p&gt;Last year, Luke Palmer wrote a post on &lt;a href=&quot;http://lukepalmer.wordpress.com/2010/11/17/searchable-data-types/&quot;&gt;&quot;Searchable Data Types&quot;&lt;/a&gt; that might also serve as a good introduction. In that article he led off with the easiest infinite space to search, the lazy naturals, or the 'one point compactification of the naturals'. That is to say the natural numbers extended with infinity.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LazyNat&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LazyNat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;infinity&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;LazyNat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;infinity&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; infinity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can implement Palmer's epsilon (called &lt;code&gt;lyingSearch&lt;/code&gt; in his article).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;palmer&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;LazyNat&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LazyNat&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;palmer&lt;/span&gt; p
  | p &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt;
  | otherwise = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; $ palmer $ p . &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick to making this work is that we place a requirement that the predicate that you pass has to terminate in a bounded amount of time no matter what input you give it, and since we're working with the naturals extended with &lt;code&gt;infinity&lt;/code&gt;, if no natural satisfies the predicate, we'll just keep returning a longer and longer chain of &lt;code&gt;Succ&lt;/code&gt;'s, effectively yielding &lt;code&gt;infinity&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To check to see if the returned number satisfies the predicate you can always use &lt;code&gt;p (palmer p)&lt;/code&gt;. The predicate is required to terminate in finite time, even when given infinity, so this will yield a Bool and not bottom out unless the user supplied predicate takes an unbounded amount of time.&lt;/p&gt;
&lt;p&gt;I posted a reply to Luke's article when it came up on reddit which included a Hinze-style generic implementation of his &lt;code&gt;lyingSearch&lt;/code&gt; predicate, which you can see now is just Hilbert's epsilon for arbitrary recursive polynomial data types.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.reddit.com/r/haskell/comments/e7nij/searchable_data_types/c15zs6l&quot;&gt;http://www.reddit.com/r/haskell/comments/e7nij/searchable_data_types/c15zs6l&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another space we can search is &lt;a href=&quot;http://en.wikipedia.org/wiki/Cantor_space&quot;&gt;the Cantor space&lt;/a&gt; 2^N.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we jump clear from countable infinity to uncountable infinity, but it can still be searched in finite time!&lt;/p&gt;
&lt;p&gt;This is the space we'll be paying attention to for the rest of this article.&lt;/p&gt;
&lt;p&gt;First we'll define how to &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Hilbert's_paradox_of_the_Grand_Hotel&quot;&gt;book a room in Hilbert's Hotel&lt;/a&gt;.&quot;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; #
(#) :: &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt;
(x # a) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = x
(x # a) i = a (i - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then this can be used to obtain the following implementation of Hilbert's epsilon for the Cantor space, attributed by Andrej to Ulrich Berger.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;berger&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;berger&lt;/span&gt; p =
  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; ex $ \a -&amp;gt; p $ &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; # a
  &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; # berger $ \a -&amp;gt; p $ &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; # a
  &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;  # berger $ \a -&amp;gt; p $ &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; # a
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; ex q = q (berger q)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This version is particularly close in structure to the one for searching the LazyNats, but it is dreadfully slow!&lt;/p&gt;
&lt;p&gt;It would be nice to be able to search the space faster and that is just what Martin Escardo's improved version does, through a more sophisticated divide and conquer technique.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;escardo&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;escardo&lt;/span&gt; p = go x l r &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go x l r n =  &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; divMod n &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) -&amp;gt; x
    (q, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) -&amp;gt; l q
    (q, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) -&amp;gt; r $ q-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
  x = ex $ \l -&amp;gt; ex $ \r -&amp;gt; p $ go &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; l r
  l = escardo $ \l -&amp;gt; ex $ \r -&amp;gt; p $ go x l r
  r = escardo $ \r -&amp;gt; p $ go x l r
  ex q = q (escardo q)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To proceed from here I'll need a State monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runS&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (a, s') -&amp;gt; (f a, s')
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = return
  (&amp;lt; *&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; $ \s -&amp;gt; (a, s)
  &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (a, s') -&amp;gt; runS (k a) s'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now we've reached the point. From here, Andrej's pure code ends, and his side-effecting ocaml and custom programming language start. The first thing he does is compute the modulus of continuity by using a side-effect that writes to a reference cell which he very carefully ensures doesn't leak out of scope, so he doesn't have to concern himself with the proposition code editing the value of the reference.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;ocaml code&quot;&gt;&lt;code class=&quot;language-ocaml&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; mu f a =
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; r = &lt;span class=&quot;hljs-built_in&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; b n = (r := max n ! r; a n) &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt;
    ignore (f b);
    !r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To obtain the same effect we'll instead make a predicate using the state monad to model the single reference cell.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- bad&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulus&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; b, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; s) =&amp;gt;
  ((s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; s a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; b c) -&amp;gt; (s -&amp;gt; a) -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can mash b and s together, and try to make the ordering and number agree by claiming that it is instead Real and we'd get the slightly more reasonable looking type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- still bad&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulus&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; a =&amp;gt;
  ((a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n c) -&amp;gt; (a -&amp;gt; b) -&amp;gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the imperative code, lexical scoping had ensured that no other code could edit the reference cell, but with this type we don't have that. The predicate is allowed to use arbitrary state actions to muck with the modulus of convergence even though the only thing that should be editing it is the wrapper beta that we placed around alpha.&lt;/p&gt;
&lt;p&gt;But how can we ensure that the end user couldn't gain access to any of the additional functionality from the monad? Parametricity!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- getting better&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulus&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; a =&amp;gt;
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f c) -&amp;gt;
  (a -&amp;gt; b) -&amp;gt;
  a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the only thing you are allowed to assume about f is that it forms a monad. This gives you access to return and &amp;gt;&amp;gt;=, but the predicate can't do anything interesting with them. All it can do is work with what is effectively the identity monad, since it knows no additional properties!&lt;/p&gt;
&lt;p&gt;We can have mercy on the end user and give them a little bit more syntactic sugar, since it doesn't cost us anything to let them also have access to the Applicative instance.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- good&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;modulus&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; a =&amp;gt;
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f) =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f c) -&amp;gt;
  (a -&amp;gt; b) -&amp;gt;
  a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can show Andrej's version of the modulus of convergence calculation does not need side-effects!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;modulus&lt;/span&gt; (\a -&amp;gt; a &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; &amp;gt;&amp;gt;= a) (\n -&amp;gt; n * n)
&lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Admittedly plumbing around the monadic values in our proposition is a bit inconvenient.&lt;/p&gt;
&lt;p&gt;His next example was written in a custom ocaml-like programming language. For translating his effect type into Haskell using parametricity, we'll need a CPS'd state monad, so we can retry from the current continuation while we track a map of assigned values.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; r s a = &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runK&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap = liftM
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure = return
  (&amp;lt; *&amp;gt;) = ap
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; $ \k -&amp;gt; k a
  &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; $ \k -&amp;gt; m $ \a -&amp;gt; runK (f a) k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For those of you who have been paying attention to my previous posts, &lt;code&gt;K r s&lt;/code&gt; is just a &lt;code&gt;Codensity&lt;/code&gt; monad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;neighborhood&lt;/span&gt; ::
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f) =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;neighborhood&lt;/span&gt; phi = snd $ runK (phi beta) (,) &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.empty &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  beta n = &lt;span class=&quot;hljs-type&quot;&gt;K&lt;/span&gt; $ \k s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.lookup n s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; b -&amp;gt; k b s
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; k &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.insert n &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; s) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      (&lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;, _) -&amp;gt; k &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.insert n &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; s)
      r -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can adapt the final version of Hilbert's epsilon for the Cantor space that Andrej provided to run in pure Haskell.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bauer&lt;/span&gt; ::
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f) =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Cantor&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;bauer&lt;/span&gt; p = \n -&amp;gt; fromMaybe &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;IntMap&lt;/span&gt;.lookup n m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  m = neighborhood p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With a little work you can implement a version of an exists and forAll predicate on top of that by running them through the identity monad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;exists&lt;/span&gt; ::
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f) =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;forAll&lt;/span&gt; ::
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; f. (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f) =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; f &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've gone further in playing with this idea, using monad homomorphisms rather than simply relying on the canonical homomorphism from the identity monad. You can get the gist of it here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/1518767&quot;&gt;https://gist.github.com/1518767&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This permits the predicates themselves to embed some limited monadic side-effects, but then you get more extensional vs. intensional issues.&lt;/p&gt;
&lt;p&gt;An obvious direction from here is to fiddle with a version of Martin Escardo's search monad that takes advantage of these techniques, but I'll leave the exploration of these ideas to the reader for now and go enjoy Christmas dinner.&lt;/p&gt;
&lt;p&gt;Happy Holidays,&lt;br&gt;
Edward Kmett&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/searching-infinity/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>What Constraints Entail: Part 2</title><link>https://comonad.com/reader/2011/what-constraints-entail-part-2/</link><guid isPermaLink="false">https://comonad.com/reader/2011/what-constraints-entail-part-2/</guid><pubDate>Thu, 03 Nov 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 3 November 2011&lt;/p&gt;&lt;span id=&quot;more-461&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/what-constraints-entail-part-1/&quot;&gt;Last time&lt;/a&gt; we derived an entailment relation for constraints, now let's get some use out of it.&lt;/p&gt;
&lt;h2 id=&quot;reflecting-classes-and-instances&quot;&gt;Reflecting Classes and Instances&lt;/h2&gt;
&lt;p&gt;Most of the implications we use on a day to day basis come from our class and instance declarations, but last time we only really dealt with constraint products.&lt;/p&gt;
&lt;p&gt;For example given:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [a]
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we could provide the following witnesses&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ordEq&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a :- &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;ordEq&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;eqList&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :- &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [a]
&lt;span class=&quot;hljs-title&quot;&gt;eqList&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this would require a lot of names and become remarkably tedious.&lt;/p&gt;
&lt;p&gt;So lets define classes to reflect the entailment provided by class definitions and instance declarations and then use them to reflect themselves.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; b h | h -&amp;gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  cls :: h :- b

&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt; :=&amp;gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; b :=&amp;gt; h | h -&amp;gt; b &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  ins :: b :- h
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; :=&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can reflect classes and instances as instances of Class and (:=&amp;gt;) respectively with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- class Eq a =&amp;gt; Ord a where ...&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- instance Eq a =&amp;gt; Eq [a] where ...&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That said, instances of Class and Instance should never require a context themselves, because the modules that the class and instance declarations live in can't taken one, so we can define the following instances which bootstrap the instances of (:=&amp;gt;) for Class and (:=&amp;gt;) once and for all.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#ifdef UNDECIDABLE&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; b a =&amp;gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; b a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; :=&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) =&amp;gt; () :=&amp;gt; b :=&amp;gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These two instances are both decidable, and following a recent bug fix, the current version of GHC HEAD supports them, but my local version isn't that recent, hence the #ifdef.&lt;/p&gt;
&lt;p&gt;We can also give admissable-if-not-ever-stated instances of Class and (:=&amp;gt;) for () as well.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;reflecting-the-prelude&quot;&gt;Reflecting the Prelude&lt;/h2&gt;
&lt;p&gt;So now that we've written a handful of instances, lets take the plunge and just reflect the entire Prelude, and (most of) the instances for the other modules we've loaded.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; ():=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; ():=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bounded&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Enum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Floating&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Floating&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Floating&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Floating&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Real&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;RealFrac&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFrac&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFrac&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFrac&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;RealFrac&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Floating&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RealFloat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ordering&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; [a] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((-&amp;gt;) a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((,) a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; ((-&amp;gt;)a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; a :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; ((,)a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; () (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; ((-&amp;gt;) a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; () :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, the structure of these definitions is extremely formulaic, so when template-haskell builds against HEAD again, they should be able to be generated automatically using splicing and reify, which would reduce this from a wall of text to a handful of lines with better coverage!&lt;/p&gt;
&lt;h2 id=&quot;an-alternative-using-default-signatures-and-type-families&quot;&gt;An alternative using Default Signatures and Type Families&lt;/h2&gt;
&lt;p&gt;Many of the above definitions could have been streamlined by using default definitions. However, MPTCs do not currently support default signatures. We can however, define Class and (:=&amp;gt;) using type families rather than functional dependencies. This enables us to use defaulting, whenever the superclass or context was ().&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Sup&lt;/span&gt; h :: &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Sup&lt;/span&gt; h = ()&lt;/span&gt;
  cls :: h :- &lt;span class=&quot;hljs-type&quot;&gt;Sup&lt;/span&gt; h
  &lt;span class=&quot;hljs-keyword&quot;&gt;default&lt;/span&gt; cls :: h :- ()
  cls = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; h :: &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; h = ()&lt;/span&gt;
  ins :: &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; h :- h
  &lt;span class=&quot;hljs-keyword&quot;&gt;default&lt;/span&gt; ins :: h =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; h :- h
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)

#ifdef &lt;span class=&quot;hljs-type&quot;&gt;UNDECIDABLE&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)
#endif

&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; ()
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; ()
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This seems at first to be a promising approach. Many instances are quite small:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; ())
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Float&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Double&lt;/span&gt;)
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But those that aren't are considerably more verbose and are much harder to read off than the definitions using the MPTC based Class and (:=&amp;gt;).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;]) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; [&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;]) = &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) = &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Complex&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) = &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ratio&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) = &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) = (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ctx&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)) = (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
  ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Having tested both approaches, the type family approach led to a ~10% larger file size, and was harder to read, so I remained with MPTCs even though it meant repeating &quot;where ins = Sub Dict&quot; over and over.&lt;/p&gt;
&lt;p&gt;In a perfect world, we'd gain the ability to use default signatures with multiparameter type classes, and the result would be considerably shorter and easier to read!&lt;/p&gt;
&lt;h2 id=&quot;fake-superclasses&quot;&gt;Fake Superclasses&lt;/h2&gt;
&lt;p&gt;Now, that we have all this machinery, it'd be nice to get something useful out of it. Even if we could derive it by other means, it'd let us know we weren't completely wasting our time.&lt;/p&gt;
&lt;p&gt;Let's define a rather horrid helper, which we'll only use where a and b are the same constraint being applied to a newtype wrapper of the same type, so we can rely on the fact that the dictionaries have the same representation.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;evil&lt;/span&gt; :: a :- b
&lt;span class=&quot;hljs-title&quot;&gt;evil&lt;/span&gt; = unsafeCoerce refl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We often bemoan the fact that we can't use Applicative sugar given just a Monad, since Applicative wasn't made a superclass of Monad due to the inability of the Haskell 98 report to foresee the future invention of Applicative.&lt;/p&gt;
&lt;p&gt;There are rather verbose options to get Applicative sugar for your Monad, or to pass it to something that expects an Applicative. For instance you can use WrappedMonad from Applicative. We reflect the relevant instance here.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;WrappedMonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using that instance and the combinators defined previously, we can obtain the following&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;applicative&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; m a. &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; m =&amp;gt; m a) -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;applicative&lt;/span&gt; m =
  m \\ trans (evil :: &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;WrappedMonad&lt;/span&gt; m) :- &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; m) ins
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here ins is instantiated to the instance of (:=&amp;gt;) above, so we use trans to compose &lt;code&gt;ins :: Monad m :- Applicative (WrappedMonad m)&lt;/code&gt; with &lt;code&gt;evil :: Applicative (WrappedMonad m) :- Applicative m&lt;/code&gt; to obtain an entailment of type &lt;code&gt;Monad m :- Applicative m&lt;/code&gt; in local scope, and then apply that transformation to discharge the Applicative obligation on m.&lt;/p&gt;
&lt;p&gt;Now, we can use this to write definitions. [Note: Frustratingly, my blog software inserts spaces after &amp;lt;'s in code]&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&amp;lt; &amp;amp;&amp;gt;) :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; m a -&amp;gt; m b -&amp;gt; m (a, b)
&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;lt; &amp;amp;&amp;gt; n = applicative $ (,) &amp;lt; $&amp;gt; m &amp;lt; *&amp;gt; n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which compares rather favorably to the more correct&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&amp;lt; &amp;amp;&amp;gt;) :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; m a -&amp;gt; m b -&amp;gt; m (a, b)
&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;lt; &amp;amp;&amp;gt; n = unwrapMonad $ (,) &amp;lt; $&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;WrapMonad&lt;/span&gt; m &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;WrapMonad&lt;/span&gt; n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;especially considering you still have access to any other instances on m you might want to bring into scope without having to use deriving to lift them onto the newtype!&lt;/p&gt;
&lt;p&gt;Similarly you can borrow &lt;code&gt;&amp;lt; |&amp;gt;&lt;/code&gt; and empty locally for use by your &lt;code&gt;MonadPlus&lt;/code&gt; with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; m :=&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;WrappedMonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; ins = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;alternative&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; m a. &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; m =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; m =&amp;gt; m a) -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;alternative&lt;/span&gt; m =
  m \\ trans (evil :: &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;WrappedMonad&lt;/span&gt; m) :- &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; m) ins
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The correctness of this of course relies upon the convention that any &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;Alternative&lt;/code&gt; your &lt;code&gt;Monad&lt;/code&gt; may have should agree with its &lt;code&gt;Monad&lt;/code&gt; instance, so even if you use &lt;code&gt;Alternative&lt;/code&gt; or &lt;code&gt;Applicative&lt;/code&gt; in a context where the actual &lt;code&gt;Applicative&lt;/code&gt; or &lt;code&gt;Alternative&lt;/code&gt; instance for your particular type m is in scope, it shouldn't matter beyond a little bit of efficiency which instance the compiler picks to discharge the &lt;code&gt;Applicative&lt;/code&gt; or &lt;code&gt;Alternative&lt;/code&gt; obligation.&lt;/p&gt;
&lt;p&gt;Note: It isn't that the &lt;code&gt;Constraint&lt;/code&gt; kind is invalid, but rather that using &lt;code&gt;unsafeCoerce&lt;/code&gt; judiciously we can bring into scope instances that don't exist for a given type by substituting those from a different type which have the right representation.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://github.com/ekmett/constraints/blob/master/Data/Constraint.hs&quot;&gt;Source&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/what-constraints-entail-part-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>What Constraints Entail: Part 1</title><link>https://comonad.com/reader/2011/what-constraints-entail-part-1/</link><guid isPermaLink="false">https://comonad.com/reader/2011/what-constraints-entail-part-1/</guid><pubDate>Thu, 03 Nov 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 3 November 2011&lt;/p&gt;&lt;span id=&quot;more-430&quot;&gt;&lt;/span&gt;&lt;p&gt;Max Bolingbroke has done a wonderful job on adding Constraint kinds to GHC.&lt;/p&gt;
&lt;p&gt;Constraint Kinds adds a new kind &lt;code&gt;Constraint&lt;/code&gt;, such that &lt;code&gt;Eq :: * -&amp;gt; Constraint&lt;/code&gt;, &lt;code&gt;Monad :: (* -&amp;gt; *) -&amp;gt; Constraint&lt;/code&gt;, but since it is a kind, we can make type families for constraints, and even parameterize constraints &lt;em&gt;on&lt;/em&gt; constraints.&lt;/p&gt;
&lt;p&gt;So, let's play with them and see what we can come up with!&lt;/p&gt;
&lt;h2 id=&quot;a-few-extensions&quot;&gt;A Few Extensions&lt;/h2&gt;
&lt;p&gt;First, we'll need a few language features:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE
  CPP,
  ScopedTypeVariables,
  FlexibleInstances,
  FlexibleContexts,
  ConstraintKinds,
  KindSignatures,
  TypeOperators,
  FunctionalDependencies,
  Rank2Types,
  StandaloneDeriving,
  GADTs
  #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because of the particular version of GHC I'm using I'll also need&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#define UNDECIDABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but this bug has been fixed in the current version of GHC Head. I'll be explicit about any instances that need UndecidableInstances by surrounding them in an &lt;code&gt;#ifdef UNDECIDABLE&lt;/code&gt; block.&lt;/p&gt;
&lt;h2 id=&quot;explicit-dictionaries&quot;&gt;Explicit Dictionaries&lt;/h2&gt;
&lt;p&gt;So with that out of the way, let's import some definitions&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Instances
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Complex
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Ratio
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Unsafe.Coerce
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and make one of our own that shows what we get out of making Constraints into a kind we can manipulate like any other.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; :: a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Previously, we coud make a Dict like data type for any one particular class constraint that we wanted to capture, but now we can write this type once and for all. The act of pattern matching on the Dict constructor will bring the constraint 'a' into scope.&lt;/p&gt;
&lt;p&gt;Of course, in the absence of incoherent and overlapping instances there is at most one dictionary of a given type, so we could make instances, like we can for any other data type, but standalone deriving is smart enough to figure these out for me. (Thanks copumpkin!)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we're willing to turn on UndecidableInstances to enable the polymorphic constraint we can even add:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#ifdef UNDECIDABLE&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; a)
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mappend &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
  mempty = &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and similar polymorphically constrained instances for &lt;code&gt;Enum&lt;/code&gt;, &lt;code&gt;Bounded&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h2 id=&quot;entailment&quot;&gt;Entailment&lt;/h2&gt;
&lt;p&gt;For that we'll need a notion of entailment.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt; :-
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; a :- b = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  _ == _ = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  compare _ _ = &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; :- &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  showsPrec d _ = showParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $
    showString &lt;span class=&quot;hljs-string&quot;&gt;&quot;Sub Dict&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we're saying that &lt;code&gt;Sub&lt;/code&gt; takes one argument, which is a computation that when implicitly given a constraint of type &lt;em&gt;a&lt;/em&gt;, can give me back a dictionary for the type &lt;em&gt;b&lt;/em&gt;. Moreover, as a newtype it adds no overhead that isn't aleady present in manipulating terms of type (a =&amp;gt; Dict b) directly.&lt;/p&gt;
&lt;p&gt;The simplest thing we can define with this is that entailment is reflexive.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;refl&lt;/span&gt; :: a :- a
&lt;span class=&quot;hljs-title&quot;&gt;refl&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Max has already written up a nice restricted monad example using these, but what I want to play with today is the category of substitutability of constraints, but there are a few observations I need to make, first.&lt;/p&gt;
&lt;p&gt;ConstraintKinds overloads &lt;code&gt;()&lt;/code&gt; and &lt;code&gt;(a,b)&lt;/code&gt; to represent the trivial constraint and the product of two constraints respectively.&lt;/p&gt;
&lt;p&gt;The latter is done with a bit of a hack, which we'll talk about in a minute, but we can use the former as a terminal object for our category of entailments.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;weaken1&lt;/span&gt; :: (a, b) :- a
&lt;span class=&quot;hljs-title&quot;&gt;weaken1&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;weaken2&lt;/span&gt; :: (a, b) :- b
&lt;span class=&quot;hljs-title&quot;&gt;weaken2&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Constraints are idempotent, so we can duplicate one, perhaps as a prelude to transforming one of them into something else.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;contract&lt;/span&gt; :: a :- (a, a)
&lt;span class=&quot;hljs-title&quot;&gt;contract&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But to do much more complicated, we're going to need a notion of substitution, letting us use our entailment relation to satisfy obligations.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; \\ &lt;span class=&quot;hljs-comment&quot;&gt;-- required comment&lt;/span&gt;
(\\) :: a =&amp;gt; (b =&amp;gt; r) -&amp;gt; (a :- b) -&amp;gt; r
&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; \\ &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; = r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The type says that given that a constraint &lt;em&gt;a&lt;/em&gt; can be satisfied, a computation that needs a constraint of type &lt;em&gt;b&lt;/em&gt; to be satisfied in order to obtain a result, and the fact that &lt;em&gt;a&lt;/em&gt; entails &lt;em&gt;b&lt;/em&gt;, we can compute the result.&lt;/p&gt;
&lt;p&gt;The constraint &lt;em&gt;a&lt;/em&gt; is satisfied by the type signature, and the fact that we get quietly passed whatever dictionary is needed. Pattern matching on Sub brings into scope a computation of type &lt;code&gt;(a =&amp;gt; Dict b)&lt;/code&gt;, and we are able to discharge the &lt;em&gt;a&lt;/em&gt; obligation, using the dictionary we were passed, Pattern matching on &lt;code&gt;Dict&lt;/code&gt; forces that computation to happen and brings b into scope, allowing us to meet the obligation of the computation of r. All of this happens for us behind the scenes just by pattern matching.&lt;/p&gt;
&lt;p&gt;So what can we do with this?&lt;/p&gt;
&lt;p&gt;We can use \\ to compose constraints.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;trans&lt;/span&gt; :: (b :- c) -&amp;gt; (a :- b) -&amp;gt; a :- c
&lt;span class=&quot;hljs-title&quot;&gt;trans&lt;/span&gt; f g = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; \\ f \\ g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact, the way the dictionaries get plumbed around inside the argument to Sub is rather nice, because we can give that same definition different type signatures, letting us make (,) more product-like, giving us the canonical product morphism to go with the weakenings/projections we defined above.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&amp;amp;&amp;amp;&amp;amp;) :: (a :- b) -&amp;gt; (a :- c) -&amp;gt; a :- (b, c)
&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &amp;amp;&amp;amp;&amp;amp; g = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; \\ f \\ g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And since we're using it as a product, we can make it act like a bifunctor also using the same definition.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(***) :: (a :- b) -&amp;gt; (c :- d) -&amp;gt; (a, c) :- (b, d)
&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; *** g = &lt;span class=&quot;hljs-type&quot;&gt;Sub&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Dict&lt;/span&gt; \\ f \\ g
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;limited-sub-superkinding&quot;&gt;Limited Sub-Superkinding?&lt;/h2&gt;
&lt;p&gt;Ideally we'd be able to capture something like that bifunctoriality using a type like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BifunctorS&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Constraint&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimapS :: (a :- b) -&amp;gt; (c :- d) -&amp;gt; p a c :- p b d
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In an even more ideal world, it would be enriched using something like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#ifdef POLYMORPHIC_KINDS&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Category&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; *) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id :: k a a
  (.) :: k b c -&amp;gt; k a b -&amp;gt; k a c
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Category&lt;/span&gt; (:-) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  id = refl
  (.) = trans
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where x is a &lt;strong&gt;kind variable&lt;/strong&gt;, then we could obtain a more baroque and admittedly far less thought-out bifunctor class like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#if 0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;z&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; p :: x -&amp;gt; x -&amp;gt; *&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; p = (-&amp;gt;)&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; p :: y -&amp;gt; y -&amp;gt; *&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; p = (-&amp;gt;)&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cod&lt;/span&gt; p :: z -&amp;gt; z -&amp;gt; *&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cod&lt;/span&gt; p = (-&amp;gt;)&lt;/span&gt;
  bimap :: &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; p a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; p c d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cod&lt;/span&gt; p (p a c) (p b d)
&lt;span class=&quot;hljs-meta&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or even more more ideally, you could use the fact that we can directly define product categories!&lt;/p&gt;
&lt;p&gt;Since they are talking about kind-indexing for classes and type families, we could have separate bifunctors for (,) for both kinds * and Constraint.&lt;/p&gt;
&lt;p&gt;The current constraint kind code uses a hack to let (a,b) be used as a type inhabiting * and as the syntax for constraints. This hack is limited however. It only works when the type (,) is fully applied to its arguments. Otherwise you'd wind up with the fact that the type (,) needs to have both of these kinds:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- (,) :: Constraint -&amp;gt; Constraint -&amp;gt; Constraint and&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- (,) :: * -&amp;gt; * -&amp;gt; *&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What is currently done is that the kind magically switches for &lt;code&gt;()&lt;/code&gt; and &lt;code&gt;(,)&lt;/code&gt; in certain circumstances. GHC already had some support for this because it parses &lt;code&gt;(Foo a, Bar b)&lt;/code&gt; as a type in &lt;code&gt;(Foo a, Bar b) =&amp;gt; Baz a b&lt;/code&gt; before transforming it into a bunch of constraints.&lt;/p&gt;
&lt;p&gt;Since we already have a notion of sub-kinding at the kind level, we could solve this for &lt;code&gt;()&lt;/code&gt; by making up a new kind, say, &lt;code&gt;???&lt;/code&gt; which is the subkind of both &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;Constraint&lt;/code&gt;, but this would break the nice join lattice properties of the current system.&lt;/p&gt;
&lt;p&gt;[Edit: in the initial draft, I had said superkind]&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;--    ?&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--   / \&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- (#)  ??&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--     /  \&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--    #    *  Constraint&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--          \ /&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--          ???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this doesn't address the kind of &lt;code&gt;(,)&lt;/code&gt; above. With the new polymorphic kinds that Brent Yorgey and company have been working on and a limited notion of sub-superkinding, this could be resolved by making a new super-kind &lt;code&gt;@&lt;/code&gt; that is the super-kind of both &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;Constraint&lt;/code&gt;, and which is a sub-superkind of the usual unnamed Box superkind.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- Box&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--  |&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--  @&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can have:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- (,) :: forall (k :: @). k -&amp;gt; k -&amp;gt; k&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- () :: forall (k :: @). k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and kind checking/inference will do the right thing about keeping the kind ambiguous for types like &lt;code&gt;(,) () :: forall (k :: @). k&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This would get rid of the hack and let me make a proper bifunctor for &lt;code&gt;(,)&lt;/code&gt; in the category of entailments.&lt;/p&gt;
&lt;p&gt;The version of GHC head I'm working with right now doesn't support polymorphic kinds, so I've only been playing with these in a toy type checker, but I'm really looking forward to being able to have product categories!&lt;/p&gt;
&lt;h2 id=&quot;stay-tuned&quot;&gt;Stay Tuned&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/what-constraints-entail-part-2/&quot;&gt;Next&lt;/a&gt;, we'll go over how to reflect the class and instance declarations so we can derive entailment of a superclass for a class, and the entailment of instances.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://github.com/ekmett/constraints/blob/master/Data/Constraint.hs&quot;&gt;Source&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/what-constraints-entail-part-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Homotopy and Directed Type Theory Slides</title><link>https://comonad.com/reader/2011/homotopy-and-directed-type-theory-slides/</link><guid isPermaLink="false">https://comonad.com/reader/2011/homotopy-and-directed-type-theory-slides/</guid><pubDate>Thu, 27 Oct 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 27 October 2011&lt;/p&gt;&lt;p&gt;As requested, here are the slides from Dan Doel's excellent presentation on &lt;a href=&quot;https://comonad.com/assets/imported/028c3f311c66-slides.pdf&quot;&gt;Homotopy and Directed Type Theory&lt;/a&gt; from this past Monday's &lt;a href=&quot;http://groups.google.com/group/bostonhaskell/browse_thread/thread/9892caece9ebb4d4&quot;&gt;Boston Haskell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/homotopy-and-directed-type-theory-slides/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Hac Boston!</title><link>https://comonad.com/reader/2011/hac-boston/</link><guid isPermaLink="false">https://comonad.com/reader/2011/hac-boston/</guid><pubDate>Tue, 25 Oct 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 October 2011&lt;/p&gt;&lt;p&gt;I am very pleased to officially announce Hac Boston, a Haskell hackathon to be held January 20-22, 2012 at MIT in Cambridge, MA. The hackathon will officially kick off at 2:30 Friday afternoon, and go until 5pm on Sunday with the occasional break for sleep.&lt;/p&gt;
&lt;p&gt;Everyone is welcome -- you do not have to be a Haskell guru to attend! Helping hack on someone else's project could be a great way to increase your Haskell skills.&lt;/p&gt;
&lt;p&gt;If you plan on coming, &lt;a href=&quot;http://haskell.org/haskellwiki/Hac_Boston/Register&quot;&gt;please officially register&lt;/a&gt;, even if you already put your name on the wiki. Registration, travel, some information about lodging and many other details can now be found on the &lt;a href=&quot;http://haskell.org/haskellwiki/Hac_Boston&quot;&gt;Hac Boston wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have confirmed space for about 30 people, so please register early! Beyond that we'll have to either seek additional space or close registration.&lt;/p&gt;
&lt;p&gt;We're also looking for a few people interested in giving short (15-20 min.) talks, probably on Saturday afternoon. Anything of interest to the Haskell community is fair game---a project you've been working on, a paper, a quick tutorial. If you'd like to give a talk, &lt;a href=&quot;http://haskell.org/haskellwiki/Hac_Boston/Talks&quot;&gt;add it on the wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We look forward to seeing you at MIT!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/hac-boston/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Parsec Full of Rats, Part 2</title><link>https://comonad.com/reader/2011/a-parsec-full-of-rats-part-2/</link><guid isPermaLink="false">https://comonad.com/reader/2011/a-parsec-full-of-rats-part-2/</guid><pubDate>Fri, 23 Sep 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 23 September 2011&lt;/p&gt;&lt;span id=&quot;more-397&quot;&gt;&lt;/span&gt;&lt;p&gt;Last time, I showed that we can build a small parsec clone with packrat support.&lt;/p&gt;
&lt;p&gt;This time I intend to implement packrat directly on top of Parsec 3.&lt;/p&gt;
&lt;p&gt;One of the main topics of discussion when it comes to packrat parsing since Bryan Ford's initial release of Pappy has been the fact that in general you shouldn't use packrat to memoize every rule, and that instead you should apply Amdahl's law to look for the cases where the lookup time is paid back in terms of repetitive evaluation, computation time and the hit rate. This is great news for us, since, we only want to memoize a handful of expensive combinators.&lt;/p&gt;
&lt;p&gt;First, we'll need to import enough of Parsec to do something interesting.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RecordWildCards, ViewPatterns, FlexibleInstances, MultiParamTypeClasses #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Parsec
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Text.Parsec.Token &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; T
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Parsec.Token
    (&lt;span class=&quot;hljs-type&quot;&gt;GenLanguageDef&lt;/span&gt;(..), &lt;span class=&quot;hljs-type&quot;&gt;GenTokenParser&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;TokenParser&lt;/span&gt;))
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Parsec.Pos (&lt;span class=&quot;hljs-title&quot;&gt;initialPos&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;updatePosChar&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor.Identity (&lt;span class=&quot;hljs-type&quot;&gt;Identity(..)&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; ((&amp;lt; |&amp;gt;))
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Fix (&lt;span class=&quot;hljs-title&quot;&gt;fix&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then as before, we'll define PEG-style backtracking:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&amp;lt; /&amp;gt;) :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ParsecT&lt;/span&gt; s u m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ParsecT&lt;/span&gt; s u m a -&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;ParsecT&lt;/span&gt; s u m a
&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &amp;lt; /&amp;gt; q = try p &amp;lt; |&amp;gt; q
&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &amp;lt; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need an analogue to our Result type from last time, which recalled whether or not we had consumed input, and what the current cursor location is. Fortunately, we can recycle the definitions from Parsec to this end.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; d a = &lt;span class=&quot;hljs-type&quot;&gt;Consumed&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Reply&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt; () a)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll define a combinator to build a parser directly from a field accessor. Last time, this was just the use of the &quot;Rat&quot; constructor. Now it is a bit trickier, because we need to turn &lt;code&gt;Consumed (Reply d () a)&lt;/code&gt; into &lt;code&gt;m (Consumed (m (Reply d u a)))&lt;/code&gt; by wrapping it in the appropriate monad, and giving the user back his state unmolested.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;rat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; (d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; d a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ParsecT&lt;/span&gt; d u m a
&lt;span class=&quot;hljs-title&quot;&gt;rat&lt;/span&gt; f   = mkPT $ \s0 -&amp;gt; return $
    return . patch s0 &amp;lt; $&amp;gt; f (stateInput s0) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  patch (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; _ _ u) (&lt;span class=&quot;hljs-type&quot;&gt;Ok&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; s p _) err) = &lt;span class=&quot;hljs-type&quot;&gt;Ok&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; s p u) err
  patch _             (&lt;span class=&quot;hljs-type&quot;&gt;Error&lt;/span&gt; e)                = &lt;span class=&quot;hljs-type&quot;&gt;Error&lt;/span&gt; e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last time we could go from a parser to a result just by applying the user stream type, but with parsec we also have to supply their notion of a position. This leads to the following combinator. By running in the Identity monad with no user state it should be obvious that we've duplicated the functionality of the previous 'Rat' parser (with the addition of a source position).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;womp&lt;/span&gt; :: d -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;SourcePos&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ParsecT&lt;/span&gt; d () &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; d a
&lt;span class=&quot;hljs-title&quot;&gt;womp&lt;/span&gt; d pos p = fmap runIdentity . runIdentity $
    runParsecT p (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; d pos ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The combinator is so named because we needed a big space-rat rather than a little pack-rat to keep with the theme.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It's not impossible. I used to bullseye womp rats in my T-16 back home, they're not much bigger than two meters.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we'll write a bit of annoyingly verbose boilerplate to convince &lt;code&gt;Parsec&lt;/code&gt; that we really want a &lt;code&gt;LanguageDef&lt;/code&gt; for some monad other than Identity. (As an aside, why &lt;code&gt;Text.Parsec.Language&lt;/code&gt; doesn't contain GenLanguageDefs that are parametric in their choice of Monad is beyond me.)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;myLanguageDef&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;GenLanguageDef&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; u m
&lt;span class=&quot;hljs-title&quot;&gt;myLanguageDef&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;LanguageDef&lt;/span&gt;
  { commentStart    = &lt;span class=&quot;hljs-string&quot;&gt;&quot;{-&quot;&lt;/span&gt;
  , commentEnd      = &lt;span class=&quot;hljs-string&quot;&gt;&quot;-}&quot;&lt;/span&gt;
  , commentLine     = &lt;span class=&quot;hljs-string&quot;&gt;&quot;--&quot;&lt;/span&gt;
  , nestedComments  = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  , identStart      = letter &amp;lt; |&amp;gt; char &lt;span class=&quot;hljs-string&quot;&gt;'_'&lt;/span&gt;
  , identLetter     = alphaNum &amp;lt; |&amp;gt; oneOf &lt;span class=&quot;hljs-string&quot;&gt;&quot;_'&quot;&lt;/span&gt;
  , opStart         = opLetter myLanguageDef
  , opLetter        = oneOf &lt;span class=&quot;hljs-string&quot;&gt;&quot;:!#$%&amp;amp;*+./&amp;lt; =&amp;gt;?@\\^|-~&quot;&lt;/span&gt;
  , reservedOpNames = []
  , reservedNames   = []
  , caseSensitive   = &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a shameless plug, trifecta offers a particularly nice solution to this problem, breaking up the monolithic Token type into separate concerns and letting you layer parser transformers that enrich the parser to deal with things like Haskell-style layout, literate comments, parsing comments in whitespace, etc.&lt;/p&gt;
&lt;p&gt;And as one last bit of boilerplate, we'll abuse RecordWildcards once again to avoid the usual 20 lines of boilerplate that are expected of us, so we can get access to parsec's token parsers.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;TokenParser&lt;/span&gt; {..} = &lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;.makeTokenParser myLanguageDef
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we're ready to define our incredibly straightforward stream type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;&lt;/span&gt;
  { _add        :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
  , _mult       :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
  , _primary    :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
  , _dec        :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
  , _uncons     :: &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;)
  }
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; m &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  uncons = return . _uncons
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And using the general purpose &lt;code&gt;rat&lt;/code&gt; combinator from earlier, we can write some memoized parsers:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;add&lt;/span&gt;, mult, primary, dec :: &lt;span class=&quot;hljs-type&quot;&gt;Parsec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; u &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;add&lt;/span&gt;     = rat _add
&lt;span class=&quot;hljs-title&quot;&gt;mult&lt;/span&gt;    = rat _mult
&lt;span class=&quot;hljs-title&quot;&gt;primary&lt;/span&gt; = rat _primary
&lt;span class=&quot;hljs-title&quot;&gt;dec&lt;/span&gt;     = rat _dec
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we write the code to tie the knot and build the stream:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;SourceName&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; n = go (initialPos n) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go p s = fix $ \d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
    (womp d p -&amp;gt; _add) =
            (+) &amp;lt; $&amp;gt; mult &amp;lt; * reservedOp &lt;span class=&quot;hljs-string&quot;&gt;&quot;+&quot;&lt;/span&gt; &amp;lt;*&amp;gt; add
        &amp;lt; /&amp;gt; mult &amp;lt; ?&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;summand&quot;&lt;/span&gt;
    (womp d p -&amp;gt; _mult) =
            (*) &amp;lt; $&amp;gt; primary &amp;lt; * reservedOp &lt;span class=&quot;hljs-string&quot;&gt;&quot;*&quot;&lt;/span&gt; &amp;lt;*&amp;gt; mult
        &amp;lt; /&amp;gt; primary &amp;lt; ?&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;factor&quot;&lt;/span&gt;
    (womp d p -&amp;gt; _primary) =
            parens add
        &amp;lt; /&amp;gt; dec &amp;lt; ?&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;number&quot;&lt;/span&gt;
    (womp d p -&amp;gt; _dec) = natural
    _uncons = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      (x:xs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (x, go (updatePosChar p x) xs)
      []     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; { .. }

&lt;span class=&quot;hljs-title&quot;&gt;runD&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Parsec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; u a -&amp;gt; u -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;SourceName&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ParseError&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;runD&lt;/span&gt; p u fn s = runParser p u fn (prep fn s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and finally, let it rip:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; s = either (error . show) id $
    runD (whiteSpace *&amp;gt; add &amp;lt; * eof) () &lt;span class=&quot;hljs-string&quot;&gt;&quot;-&quot;&lt;/span&gt; s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this approach tends to encourage memoizing fewer combinators than libraries such as frisby, this is exactly what &lt;a href=&quot;http://www.mercury.csse.unimelb.edu.au/information/papers/packrat.pdf&quot;&gt;current research suggests you probably should do&lt;/a&gt; with packrat parsing!&lt;/p&gt;
&lt;p&gt;The other purported advantage of packrat parsers is that they &lt;a href=&quot;http://www.vpri.org/pdf/tr2007002_packrat.pdf&quot;&gt;can deal with left recursion in the grammar&lt;/a&gt;. However, that is not the case, hidden left recursion in the presence of the algorithm used in the scala parsing combinator libraries leads to incorrect non-left-most parses &lt;a href=&quot;http://tratt.net/laurie/research/publications/papers/tratt__direct_left_recursive_parsing_expression_grammars.pdf&quot;&gt;as shown by Tratt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I leave it as an exercise for the reader to extend this material with the parsec+iteratees approach from my original talk on trifecta to get packrat parsing of streaming input. Either that or you can wait until it is integrated into trifecta.&lt;/p&gt;
&lt;p&gt;You can download the source to this (without the spurious spaces inserted by wordpress) &lt;a href=&quot;https://github.com/ekmett/trifecta/blob/master/wip/Womprat.hs&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If I can find the time, I hope to spend some time addressing Scott and Johnstone's GLL parsers, which actually achieve the O(n^3) worst case bounds touted for Tomita's GLR algorithm (which is actually O(n^4) as it was originally defined despite the author's claims), and how to encode them in Haskell with an eye towards building a memoizing parser combinator library that can parse LL(1) fragments in O(1), deal with arbitrary context-free grammars in O(n^3), and degrade reasonably gracefully in the presence of context-sensitivity, while supporting hidden left recursion as long as such recursion passes through at least one memoized rule. This is important because CFGs are closed under extensions to the grammar, which is a nice property to have if you want to have a language where you can add new statement types easily without concerning yourself overmuch with the order in which you insert the rules or load the different extensions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/a-parsec-full-of-rats-part-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Parsec Full of Rats, Part 1</title><link>https://comonad.com/reader/2011/a-parsec-full-of-rats/</link><guid isPermaLink="false">https://comonad.com/reader/2011/a-parsec-full-of-rats/</guid><pubDate>Fri, 23 Sep 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 23 September 2011&lt;/p&gt;&lt;span id=&quot;more-380&quot;&gt;&lt;/span&gt;&lt;blockquote&gt;
&lt;p&gt;You never heard of the Millenium Falcon? It's the ship that made the Kessel Run in 12 parsecs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I've been working on a parser combinator library called &lt;a href=&quot;https://hackage.haskell.org/package/trifecta&quot;&gt;trifecta&lt;/a&gt;, and so I decided I'd share some thoughts on parsing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pdos.csail.mit.edu/~baford/packrat/&quot;&gt;Packrat parsing&lt;/a&gt; (as provided by &lt;a href=&quot;https://hackage.haskell.org/package/frisby&quot;&gt;frisby&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/package/pappy&quot;&gt;pappy&lt;/a&gt;, &lt;a href=&quot;http://cs.nyu.edu/rgrimm/xtc/&quot;&gt;rats!&lt;/a&gt; and the Scala parsing combinators) and more traditional recursive descent parsers (like Parsec) are often held up as somehow different.&lt;/p&gt;
&lt;p&gt;Today I'll show that you can add monadic parsing to a packrat parser, sacrificing asymptotic guarantees in exchange for the convenient context sensitivity, and conversely how you can easily add packrat parsing to a traditional monadic parser combinator library.&lt;/p&gt;
&lt;p&gt;To keep this post self-contained, I'm going to start by defining a small packrat parsing library by hand, which acts rather like parsec in its backtracking behavior. First, some imports:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE RecordWildCards, ViewPatterns, DeriveFunctor #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad (&lt;span class=&quot;hljs-type&quot;&gt;MonadPlus(..)&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;guard&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Fix (&lt;span class=&quot;hljs-title&quot;&gt;fix&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Char (&lt;span class=&quot;hljs-title&quot;&gt;isDigit&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;digitToInt&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;isSpace&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, we'll define a bog simple parser, which consumes an input stream of type d, yielding a possible answer and telling us whether or not it has actually consumed any input as it went.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runRat&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; d a&lt;/span&gt;
  = &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a             &lt;span class=&quot;hljs-comment&quot;&gt;-- didn't consume anything, can backtrack&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d a      &lt;span class=&quot;hljs-comment&quot;&gt;-- consumed input&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- failed, flagged if consumed&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can finally implement some type classes:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \ _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; mf &amp;lt; *&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; ma = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \ d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; mf d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; f      -&amp;gt; fmap f (ma d)
    &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s c    -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s c
    &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d' f -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ma d' &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a       -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d' (f a)
      &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s _     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d'' a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d'' (f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;including an instance of Alternative that behaves like parsec, only backtracking on failure if no input was unconsumed.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; ma &amp;lt; |&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; mb = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \ d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; ma d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; _ &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt; -&amp;gt; mb d
    x            -&amp;gt; x
  empty = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \ _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;empty&quot;&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For those willing to forego the asymptotic guarantees of packrat, we'll offer a monad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \_ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a -&amp;gt; runRat (k a) d
    &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d' a -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; runRat (k a) d' &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; d' b
      &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;
      commit -&amp;gt; commit
    &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s c
  fail s = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \ _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadPlus&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;d&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mplus = (&amp;lt; |&amp;gt;)
  mzero = empty
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and a Parsec-style &quot;try&quot;, which rewinds on failure, so that &amp;lt; |&amp;gt; can try again.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;try&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a
&lt;span class=&quot;hljs-title&quot;&gt;try&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s _ -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
  x        -&amp;gt; x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we've consumed &amp;lt; |&amp;gt; with parsec semantics. Let's give a PEG-style backtracking (&amp;lt; /&amp;gt;).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&amp;lt; /&amp;gt;) :: &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a
&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &amp;lt; /&amp;gt; q = try p &amp;lt; |&amp;gt; q
&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; &amp;lt; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far nothing we have done involves packrat at all. These are all general purpose recursive descent combinators.&lt;/p&gt;
&lt;p&gt;We can define an input stream and a number of combinators to read input.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  anyChar :: &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;whiteSpace&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d ()
&lt;span class=&quot;hljs-title&quot;&gt;whiteSpace&lt;/span&gt; = () &amp;lt; $ many (satisfy isSpace)
&lt;span class=&quot;hljs-title&quot;&gt;phrase&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a
&lt;span class=&quot;hljs-title&quot;&gt;phrase&lt;/span&gt; m = whiteSpace *&amp;gt; m &amp;lt; * eof

&lt;span class=&quot;hljs-title&quot;&gt;notFollowedBy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d ()
&lt;span class=&quot;hljs-title&quot;&gt;notFollowedBy&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; m d &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt;{} -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; ()
  _      -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;unexpected&quot;&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;eof&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d ()
&lt;span class=&quot;hljs-title&quot;&gt;eof&lt;/span&gt; = notFollowedBy anyChar

&lt;span class=&quot;hljs-title&quot;&gt;satisfy&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;satisfy&lt;/span&gt; p = try $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  x &amp;lt; - anyChar
  x &amp;lt;$ guard (p x)

&lt;span class=&quot;hljs-title&quot;&gt;char&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;char&lt;/span&gt; c = satisfy (c ==)

&lt;span class=&quot;hljs-title&quot;&gt;lexeme&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d a
&lt;span class=&quot;hljs-title&quot;&gt;lexeme&lt;/span&gt; m = m &amp;lt; * whiteSpace

&lt;span class=&quot;hljs-title&quot;&gt;symbol&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;symbol&lt;/span&gt; c = lexeme (char c)

&lt;span class=&quot;hljs-title&quot;&gt;digit&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; d =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; d &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;digit&lt;/span&gt; = digitToInt &amp;lt; $&amp;gt; satisfy isDigit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can of course use a string as our input stream:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  anyChar = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; $ \s -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (x:xs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; xs x
    [] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;EOF&quot;&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we've built a poor man's Parsec, let's do something more interesting. Instead of just using String as out input stream, let's include slots for use in memoizing the results from our various parsers at each location. To keep things concrete, we'll memoize the ArithPackrat.hs example that Bryan Ford used in his initial packrat presentation enriched with some whitespace handling.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;&lt;/span&gt;
  { _add        :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  , _mult       :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  , _primary    :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  , _decimal    :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
  , anyCharD    :: &lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Char&lt;/span&gt;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you look at the type of each of those functions you'll see that &lt;code&gt;_add :: D -&amp;gt; Result D Int&lt;/code&gt;, which is exactly our Rat newtype expects as its argument, we we can bundle them directly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;add&lt;/span&gt;, mult, primary, decimal :: &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;add&lt;/span&gt;     = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; _add
&lt;span class=&quot;hljs-title&quot;&gt;mult&lt;/span&gt;    = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; _mult
&lt;span class=&quot;hljs-title&quot;&gt;primary&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; _primary
&lt;span class=&quot;hljs-title&quot;&gt;decimal&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; _decimal
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can similarly juse use the character parse result.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  anyChar = &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; anyCharD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we just need to build a D from a String. I'm using view patterns and record wildcards to shrink the amount of repetitive naming.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;parse&lt;/span&gt; s = fix $ \d -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; (dv d -&amp;gt; _add) =
        (+) &amp;lt; $&amp;gt; mult &amp;lt; * symbol &lt;span class=&quot;hljs-string&quot;&gt;'+'&lt;/span&gt; &amp;lt;*&amp;gt; add
     &amp;lt; /&amp;gt; mult
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; (dv d -&amp;gt; _mult) =
        (*) &amp;lt; $&amp;gt; primary &amp;lt; * symbol &lt;span class=&quot;hljs-string&quot;&gt;'*'&lt;/span&gt; &amp;lt;*&amp;gt; mult
    &amp;lt; /&amp;gt; primary
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; (dv d -&amp;gt; _primary) =
        symbol &lt;span class=&quot;hljs-string&quot;&gt;'('&lt;/span&gt; *&amp;gt; add &amp;lt; * symbol &lt;span class=&quot;hljs-string&quot;&gt;')'&lt;/span&gt;
    &amp;lt;/&amp;gt; decimal
  &lt;span class=&quot;hljs-type&quot;&gt;Rat&lt;/span&gt; (dv d -&amp;gt; _decimal) =
     foldl' (\b a -&amp;gt; b * &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; + a) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;lt; $&amp;gt; lexeme (some digit)
  anyCharD = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
    (x:xs) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; (parse xs) x
    []     -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;EOF&quot;&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;False&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; { .. }

&lt;span class=&quot;hljs-title&quot;&gt;dv&lt;/span&gt; :: d -&amp;gt; (d -&amp;gt; b) -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;dv&lt;/span&gt; d f = f d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we didn't really bother factoring the grammar, since packrat will take care of memoizing the redundant calls!&lt;/p&gt;
&lt;p&gt;And with that, we can define an evaluator.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; s = &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; runRat (whiteSpace *&amp;gt; add &amp;lt; * eof) (parse s) &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a -&amp;gt; a
  &lt;span class=&quot;hljs-type&quot;&gt;Commit&lt;/span&gt; _ a -&amp;gt; a
  &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; s _ -&amp;gt; error s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that because the input stream D contains the result directly and parse is the only thing that ever generates a D, and it does so when we start up, it should be obvious that the parse results for each location can't depend on any additional information smuggled in via our monad.&lt;/p&gt;
&lt;p&gt;Next time, we'll add a packratted Stream type directly to Parsec, which will necessitate some delicate handling of user state.&lt;/p&gt;
&lt;p&gt;The small parser implemented here can be &lt;a href=&quot;https://github.com/ekmett/trifecta/blob/master/wip/Rat.hs&quot;&gt;found on my github account&lt;/a&gt;, where it hasn't been adulterated with unnecessary spaces by my blog software.&lt;/p&gt;
&lt;p&gt;P.S. To explain the quote, had I thought of it earlier, I could have named my parsing combinator library &quot;Kessel Run&quot; as by the time I'm done with it &quot;it will contain at least 12 parsecs&quot; between its different parser implementations.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/a-parsec-full-of-rats/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Free Modules and Functional Linear Functionals</title><link>https://comonad.com/reader/2011/free-modules-and-functional-linear-functionals/</link><guid isPermaLink="false">https://comonad.com/reader/2011/free-modules-and-functional-linear-functionals/</guid><pubDate>Mon, 11 Jul 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 11 July 2011&lt;/p&gt;&lt;span id=&quot;more-356&quot;&gt;&lt;/span&gt;&lt;p&gt;Today I hope to start a new series of posts exploring constructive abstract algebra in Haskell.&lt;/p&gt;
&lt;p&gt;In particular, I want to talk about a novel encoding of linear functionals, polynomials and linear maps in Haskell, but first we're going to have to build up some common terminology.&lt;/p&gt;
&lt;p&gt;Having obtained the blessing of Wolfgang Jeltsch, I replaced the &lt;a href=&quot;https://hackage.haskell.org/package/algebra&quot;&gt;algebra&lt;/a&gt; package on hackage with something... bigger, although still very much a work in progress.&lt;/p&gt;
&lt;h2 id=&quot;infinite-modules-over-semirings&quot;&gt;(Infinite) Modules over Semirings&lt;/h2&gt;
&lt;p&gt;Recall that a vector space &lt;strong&gt;V&lt;/strong&gt; over a field &lt;strong&gt;F&lt;/strong&gt; is given by an additive Abelian group on &lt;strong&gt;V&lt;/strong&gt;, and a scalar multiplication operator&lt;br&gt;
&lt;code&gt;(.*) :: F -&amp;gt; V -&amp;gt; V&lt;/code&gt; subject to distributivity laws&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; .* (u + v) = s .* u + s .* v
(s + t) .* v = s .* v + t .* v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and associativity laws&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;   (s * t) .* v = s .* (t .* v)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and respect of the unit of the field.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;   &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; .* v = v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since multiplication on a field is commutative, we can also add&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;  (*.) :: &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;V&lt;/span&gt;
  v *. f = f .* v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with analogous rules.&lt;/p&gt;
&lt;p&gt;But when F is only a &lt;a href=&quot;http://en.wikipedia.org/wiki/Ring_(mathematics)&quot;&gt;Ring&lt;/a&gt;, we call the analogous structure a module, and in a ring, we can't rely on the commutativity of multiplication, so we may have to deal left-modules and right-modules, where only one of those products is available.&lt;/p&gt;
&lt;p&gt;We can weaken the structure still further. If we lose the negation in our Ring we and go to a &lt;a href=&quot;http://en.wikipedia.org/wiki/Semiring&quot;&gt;Rig&lt;/a&gt; (often called a Semiring), now our module is an additive moniod.&lt;/p&gt;
&lt;p&gt;If we get rid of the additive and multiplicative unit on our Rig we get down to what some authors call a Ringoid, but which we'll call a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/algebra/0.3.0/doc/html/Numeric-Semiring-Class.html&quot;&gt;Semiring&lt;/a&gt; here, because it makes the connection between semiring and semigroup clearer, and the &lt;em&gt;-oid&lt;/em&gt; suffix is dangerously overloaded due to category theory.&lt;/p&gt;
&lt;p&gt;First we'll define additive semigroups, because I'm going to need both additive and multiplicative monoids over the same types, and Data.Monoid has simultaneously too much and too little structure.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- (a + b) + c = a + (b + c)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (+) :: m -&amp;gt; m -&amp;gt; m
  replicate1p :: &lt;span class=&quot;hljs-type&quot;&gt;Whole&lt;/span&gt; n =&amp;gt; n -&amp;gt; m -&amp;gt; m &lt;span class=&quot;hljs-comment&quot;&gt;-- (ignore this for now)&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;their Abelian cousins&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- a + b = b + a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Abelian&lt;/span&gt; m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and Multiplicative semigroups&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- (a * b) * c = a * (b * c)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Multiplicative&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  (*) :: m -&amp;gt; m -&amp;gt; m
  pow1p :: &lt;span class=&quot;hljs-type&quot;&gt;Whole&lt;/span&gt; n =&amp;gt; m -&amp;gt; n -&amp;gt; m
  &lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can define a semirings&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- a*(b + c) = a*b + a*c&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- (a + b)*c = a*c + b*c&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Abelian&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Multiplicative&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Semiring&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can define modules over a semiring:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- r .* (x + y) = r .* x + r .* y&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- (r + s) .* x = r .* x + s .* x&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- (r * s) .* x = r .* (s .* x)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Semiring&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; r m
   (.*) :: r -&amp;gt; m -&amp;gt; m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and analogously:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Semiring&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RightModule&lt;/span&gt; r m
   (*.) :: m -&amp;gt; r -&amp;gt; m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For instance every additive semigroup forms a semiring module over the positive natural numbers (1,2..) using replicate1p.&lt;/p&gt;
&lt;p&gt;If we know that our addition forms a monoid, then we can form a module over the naturals as well&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | zero + a = a = a + zero&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;,
    &lt;span class=&quot;hljs-type&quot;&gt;RightModule&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Natural&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;
    ) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveMonoid&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   zero :: m
   replicate :: &lt;span class=&quot;hljs-type&quot;&gt;Whole&lt;/span&gt; n =&amp;gt; n -&amp;gt; m -&amp;gt; m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and if our addition forms a group, then we can form a module over the integers&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | a + negate a = zero = negate a + a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;
    , &lt;span class=&quot;hljs-type&quot;&gt;RightModule&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;
    ) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveGroup&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  negate :: m -&amp;gt; m
  times :: &lt;span class=&quot;hljs-type&quot;&gt;Integral&lt;/span&gt; n =&amp;gt; n -&amp;gt; m -&amp;gt; m
  &lt;span class=&quot;hljs-comment&quot;&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;free-modules-over-semirings&quot;&gt;Free Modules over Semirings&lt;/h2&gt;
&lt;p&gt;A free module on a set E, is a module where the basis vectors are elements of E. Basically it is |E| copies of some (semi)ring.&lt;/p&gt;
&lt;p&gt;In Haskell we can represent the free module of a ring directly by defining the action of the (semi)group pointwise.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Additive&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   f + g = \x -&amp;gt; f x + g x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Abelian&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Abelian&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;)

&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveMonoid&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveMonoid&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   zero = const zero
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveGroup&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditveGroup&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   f - g = \x -&amp;gt; f x - g x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could define the following&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Semiring&lt;/span&gt; r =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; r (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   r .* f = \x -&amp;gt; r * f x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but then we'd have trouble dealing with the Natural and Integer constraints above, so instead we lift modules&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; r m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; r (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   (.*) m f e = m .* f e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RightModule&lt;/span&gt; r m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;RightModule&lt;/span&gt; r (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   (*.) f m e = f e *. m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We &lt;strong&gt;could&lt;/strong&gt; go one step further and define multiplication pointwise, but while the direct product of |e| copies of a ring _does_ define a ring, and this ring is the one provided by the Conal Elliot's &lt;a href=&quot;http://code.haskell.org/vector-space/&quot;&gt;&lt;code&gt;vector-space&lt;/code&gt;&lt;/a&gt; package, it isn't the most general ring we could construct. But we'll need to take a detour first.&lt;/p&gt;
&lt;h2 id=&quot;linear-functionals&quot;&gt;Linear Functionals&lt;/h2&gt;
&lt;p&gt;A Linear functional f on a module M is a linear function from a M to its scalars R.&lt;/p&gt;
&lt;p&gt;That is to say that, f : M -&amp;gt; R such that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (a .* x + y) = a * f x + f y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Consequently linear functionals also form a module over R. We call this module the dual module M*.&lt;/p&gt;
&lt;p&gt;Dan Piponi has blogged about these dual vectors (or covectors) in the context of trace diagrams.&lt;/p&gt;
&lt;p&gt;If we limit our discussion to free modules, then M = E -&amp;gt; R, so a linear functional on M looks like &lt;code&gt;(E -&amp;gt; R) -&amp;gt; R&lt;/code&gt;&lt;br&gt;
&lt;em&gt;subject to additional linearity constraints&lt;/em&gt; on the result arrow.&lt;/p&gt;
&lt;p&gt;The main thing we're not allowed to do in our function is apply our function from E -&amp;gt; R to two different E's and then multiply the results together. Our pointwise definitions above satisfy those linearity constraints, but for example:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bad&lt;/span&gt; f = f &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; * f &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;does not.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; capture this invariant in the type by saying that instead we want&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LinearM&lt;/span&gt; r e =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;LinearM&lt;/span&gt; {
    runLinearM :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. &lt;span class=&quot;hljs-type&quot;&gt;LeftModule&lt;/span&gt; r m =&amp;gt; (e -&amp;gt; m) -&amp;gt; m
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we'd have to make a new such type every time we subclassed Semiring. I'll leave further exploration of this more exotic type to another time. (Using some technically illegal module instances we can recover more structure that you'd expect.)&lt;/p&gt;
&lt;p&gt;Now we can package up the type of covectors/linear functionals:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; $*
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; r a = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; { ($*) :: (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sufficiently observant may have already noticed that this type is the same as the Cont monad (subject to the linearity restriction on the result arrow).&lt;/p&gt;
&lt;p&gt;In fact the &lt;code&gt;Functor&lt;/code&gt;, &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt; instances for &lt;code&gt;Cont&lt;/code&gt; all carry over, and &lt;strong&gt;preserve linearity&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;(We lose &lt;code&gt;callCC&lt;/code&gt;, but that is at least partially due to the fact that &lt;code&gt;callCC&lt;/code&gt; has a less than ideal type signature.)&lt;/p&gt;
&lt;p&gt;In addition we get a number of additional instances for &lt;code&gt;Alternative&lt;/code&gt;, &lt;code&gt;MonadPlus&lt;/code&gt;, by exploiting the knowledge that r is ring-like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AdditiveMonoid&lt;/span&gt; r =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Alternative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; f &amp;lt; |&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; g = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; (f + g)
  empty = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; zero
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the &lt;code&gt;(+)&lt;/code&gt; and &lt;code&gt;zero&lt;/code&gt; there are the ones defined on functions from our earlier free module construction!&lt;/p&gt;
&lt;h2 id=&quot;linear-maps&quot;&gt;Linear Maps&lt;/h2&gt;
&lt;p&gt;Since &lt;code&gt;Linear r&lt;/code&gt; is a monad, &lt;code&gt;Kleisli (Linear r)&lt;/code&gt; forms an &lt;code&gt;Arrow&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; ((a -&amp;gt; r) ~&amp;gt; r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the ~&amp;gt; denotes the arrow that is constrained to be linear.&lt;/p&gt;
&lt;p&gt;If we swap the order of the arguments so that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(a -&amp;gt; r) ~&amp;gt; (b -&amp;gt; r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this arrow has a very nice meaning! (See &lt;a href=&quot;https://hackage.haskell.org/packages/archive/algebra/0.4.0/doc/html/Numeric-Map-Linear.html&quot;&gt;Numeric.Map.Linear&lt;/a&gt;)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; $#
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; r b a = &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; { ($#) :: (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Map r b a&lt;/code&gt; represents the type of &lt;a href=&quot;http://en.wikipedia.org/wiki/Linear_map&quot;&gt;linear maps&lt;/a&gt; from &lt;code&gt;a -&amp;gt; b&lt;/code&gt;. Unfortunately due to contravariance the arguments wind up in the &quot;wrong&quot; order.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Category&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; f . &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; g = &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; (g . f)
  id = &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we can see that a linear map from a module A with basis &lt;code&gt;a&lt;/code&gt; to a vector space with basis &lt;code&gt;b&lt;/code&gt; effectively consists of |b| linear functionals on A.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Map r b a&lt;/code&gt; provides a lot of structure. It is a valid instance of &lt;a href=&quot;https://github.com/ekmett/algebra/blob/master/Numeric/Map/Linear.hs&quot;&gt;an insanely large number of classes&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;vectors-and-covectors&quot;&gt;Vectors and Covectors&lt;/h2&gt;
&lt;p&gt;In physics, we sometimes call linear functionals &lt;a href=&quot;http://www.euclideanspace.com/maths/algebra/vectors/related/covector/index.htm&quot;&gt;covectors&lt;/a&gt; or covariant vectors, and if we're feeling particularly loquacious, we'll refer to vectors as contravariant vectors.&lt;/p&gt;
&lt;p&gt;This has to do with the fact that when you change basis, you change map the change over covariant vectors covariantly, and map the change over vectors contravariantly. (This distinction is beautifully captured by &lt;a href=&quot;http://en.wikipedia.org/wiki/Einstein_notation&quot;&gt;Einstein's summation notation&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;We also have a notion of &lt;a href=&quot;http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)&quot;&gt;covariance and contravariance in computer science&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Functions vary covariantly in their result, and contravariant in their argument. &lt;code&gt;E -&amp;gt; R&lt;/code&gt; is contravariant in E. But we chose this representation for our free modules, so the vectors in our free vector space (or module) are contravariant in E.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  contramap :: (a -&amp;gt; b) -&amp;gt; f a -&amp;gt; f b

&lt;span class=&quot;hljs-comment&quot;&gt;-- | Dual function arrows.&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getOp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  contramap f g = &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; (getOp g . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other hand &lt;code&gt;(E -&amp;gt; R) ~&amp;gt; R&lt;/code&gt; varies covariantly with the change of &lt;code&gt;E&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;as witnessed by the fact that it is a &lt;code&gt;Functor&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f m = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; $ \k -&amp;gt; m $* k . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have lots of classes for manipulating covariant structures, and most of them apply to both (Linear r) and (Map r b).&lt;/p&gt;
&lt;h2 id=&quot;other-representations-and-design-trade-offs&quot;&gt;Other Representations and Design Trade-offs&lt;/h2&gt;
&lt;p&gt;One common representation of vectors in a free vector space is as some kind of normalized list of scalars and basis vectors. In particular, David Amos's wonderful &lt;a href=&quot;http://www.polyomino.f2s.com/david/haskell/main.html&quot;&gt;HaskellForMaths&lt;/a&gt; uses&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; r a = &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runVect&lt;/span&gt; :: [(&lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;for free vector spaces, only considering them up to linearity, paying for normalization as it goes.&lt;/p&gt;
&lt;p&gt;Given the insight above we can see that Vect isn't a representation of vectors in the free vector space, but instead represents the covectors of that space, quite simply because Vect r a varies covariantly with change of basis!&lt;/p&gt;
&lt;p&gt;Now the price of using the &lt;code&gt;Monad&lt;/code&gt; on &lt;code&gt;Vect r&lt;/code&gt; is that the monad denormalizes the representation. In particular, you can have multiple copies of the same basis vector., so any function that uses &lt;code&gt;Vect r a&lt;/code&gt; has to merge them together.&lt;/p&gt;
&lt;p&gt;On the other hand with the directly encoded linear functionals we've described here, we've placed no obligations on the consumer of a linear functional. They can feed the directly encoded linear functional &lt;strong&gt;any vector&lt;/strong&gt; they want!&lt;/p&gt;
&lt;p&gt;In fact, it'll even be quite a bit more efficient to compute,&lt;/p&gt;
&lt;p&gt;To see this, just consider:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MultiplicativeMonoid&lt;/span&gt; r =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return a = &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,a)]
   &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt;
       [ (p*q, b) | (p,a) &amp;lt; - &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;, (q,b) &amp;lt;- runVect (f b) ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every &amp;gt;&amp;gt;= must pay for multiplication. Every return will multiply the element by one. On the other hand, the price of return and bind in Linear r is function application.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; $ \k -&amp;gt; k a
  m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; $ \k -&amp;gt; m $* \a -&amp;gt; f a $* k
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;a-digression-on-free-linear-functionals&quot;&gt;A Digression on Free Linear Functionals&lt;/h2&gt;
&lt;p&gt;To wax categorical for a moment, we can construct a forgetful functor &lt;code&gt;U : Vect_F -&amp;gt; Set&lt;/code&gt; that takes a vector space over F to just its set of covectors.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt; = (&lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;,\f g x -&amp;gt; f x + g x ,\r f x -&amp;gt; r * f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;using the pointwise constructions we built earlier.&lt;/p&gt;
&lt;p&gt;Then in a classical setting, you can show that F is left adjoint to U.&lt;/p&gt;
&lt;p&gt;In particular the witnesses of this adjunction provide the linear map from (E -&amp;gt; F) to V and the function E -&amp;gt; (V ~&amp;gt; F) giving a linear functional on V for each element of E.&lt;/p&gt;
&lt;p&gt;In a classical setting you can go a lot farther, and show that all vector spaces (but not all modules) are free.&lt;/p&gt;
&lt;p&gt;But in a constructive setting, such as Haskell, we need a fair bit to go back and forth, in particular we wind up need E to be finitely enumerable to go one way, and for it to have decidable equality to go in the other. The latter is fairly easy to see, because even going from &lt;code&gt;E -&amp;gt; (E -&amp;gt; F)&lt;/code&gt; requires that we can define and partially apply something like &lt;a href=&quot;http://en.wikipedia.org/wiki/Kronecker_delta&quot;&gt;Kronecker's delta&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;delta&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Rig&lt;/span&gt; r, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a) =&amp;gt; e -&amp;gt; e -&amp;gt; r
&lt;span class=&quot;hljs-title&quot;&gt;delta&lt;/span&gt; i j | i == j = one
       | otherwise = zero
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-price-of-power&quot;&gt;The Price of Power&lt;/h2&gt;
&lt;p&gt;The price we pay is that, given a &lt;code&gt;Rig&lt;/code&gt;, we can go from &lt;code&gt;Vect r a&lt;/code&gt; to &lt;code&gt;Linear r a&lt;/code&gt; but going back requires &lt;code&gt;a&lt;/code&gt; to be be finitely enumerable (or for our functional to satisfy other exotic side-conditions).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;vectMap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rig&lt;/span&gt; r =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; r a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; r a
&lt;span class=&quot;hljs-title&quot;&gt;vectMap&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; $ \k -&amp;gt; sum [ r * k a | (r, a) &amp;lt; - &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can still probe &lt;code&gt;Linear r a&lt;/code&gt; for individual coefficients, or pass it a vector for polynomial evaluation very easily, but for instance determining a degree of a polynomial efficiently requires attaching more structure to your semiring, because the only value you can get out of &lt;code&gt;Linear r a&lt;/code&gt; is an &lt;code&gt;r&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;optimizing-linear-functionals&quot;&gt;Optimizing Linear Functionals&lt;/h2&gt;
&lt;p&gt;In both the &lt;code&gt;Vect r&lt;/code&gt; and &lt;code&gt;Linear r&lt;/code&gt; cases, excessive use of &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; without somehow normalizing or tabulating your data will cause a &lt;strong&gt;lot&lt;/strong&gt; of repeated work.&lt;/p&gt;
&lt;p&gt;This is perhaps easiest to see from the fact that &lt;code&gt;Vect r&lt;/code&gt; never used the addition of &lt;code&gt;r&lt;/code&gt;, so it distributed everything into a kind of disjunctive normal form. &lt;code&gt;Linear r&lt;/code&gt; does the same thing.&lt;/p&gt;
&lt;p&gt;If you look at the Kleisli arrows of &lt;code&gt;Vect r&lt;/code&gt; or &lt;code&gt;Linear r&lt;/code&gt; as linear mappings, then you can see that Kleisli composition is going to explode the number of terms.&lt;/p&gt;
&lt;p&gt;So how can we collapse back down?&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;Kleisli (Vect r)&lt;/code&gt; case we usually build up a map as we walk through the list then spit the list back out in order having added up like terms.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;Map r&lt;/code&gt; case, we can do better. My &lt;a href=&quot;https://hackage.haskell.org/package/representable-tries&quot;&gt;&lt;code&gt;representable-tries&lt;/code&gt;&lt;/a&gt; package provides a readily instantiable &lt;code&gt;HasTrie&lt;/code&gt; class, and the method:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;memo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HasTrie&lt;/span&gt; a =&amp;gt; (a -&amp;gt; r) -&amp;gt; a -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is responsible for providing a memoized version of the function from &lt;code&gt;a -&amp;gt; r&lt;/code&gt; in a purely functional way. This is obviously a linear map!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;memoMap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HasTrie&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; r a a
&lt;span class=&quot;hljs-title&quot;&gt;memoMap&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Map&lt;/span&gt; memo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also flip memo around and memoize linear functionals.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;memoLinear&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;HasTrie&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; r a
&lt;span class=&quot;hljs-title&quot;&gt;memoLinear&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Linear&lt;/span&gt; . flip memo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next time, (co)associative (co)algebras and the myriad means of multiplying (co)vectors!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-modules-and-functional-linear-functionals/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>A Product of an Imperfect Union</title><link>https://comonad.com/reader/2011/a-product-of-an-imperfect-union/</link><guid isPermaLink="false">https://comonad.com/reader/2011/a-product-of-an-imperfect-union/</guid><pubDate>Thu, 30 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 June 2011&lt;/p&gt;&lt;span id=&quot;more-337&quot;&gt;&lt;/span&gt;&lt;p&gt;In the last few posts, I've been talking about how we can derive &lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;monads&lt;/a&gt; and &lt;a href=&quot;https://comonad.com/reader/2011/monad-transformers-from-comonads/&quot;&gt;monad transformers&lt;/a&gt; from comonads. Along the way we learned that there are more monads than comonads in Haskell.&lt;/p&gt;
&lt;p&gt;The question I hope to answer this time, is whether or not we turn any Haskell &lt;code&gt;Comonad&lt;/code&gt; into a &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonad-transformers/1.8.0/doc/html/Control-Comonad-Trans-Class.html&quot;&gt;comonad transformer&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;comonads-from-comonads&quot;&gt;Comonads from Comonads&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;Monads from Comonads&lt;/a&gt;, we built the comonad-to-monad transformer&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w m a = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;by sandwiching a &lt;code&gt;Comonad&lt;/code&gt; &lt;em&gt;w&lt;/em&gt; in the middle of a trivial Codensity monad, then proceeded to show that at least in the case where our comonad was given rise to by an adjunction &lt;code&gt;f -| g : Hask -&amp;gt; Hask&lt;/code&gt;, we could reason about this as if we had&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w ~ &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (f . g) ~ g . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;Codensity&lt;/code&gt; monads are a right &lt;a href=&quot;http://en.wikipedia.org/wiki/Kan_extension&quot;&gt;Kan extension&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, what happens if we try to do the same thing to a Left Kan extension?&lt;/p&gt;
&lt;p&gt;Using&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE GADTs, FlexibleInstances #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad.Trans.Class
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can define&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; :: w (r -&amp;gt; a) -&amp;gt; r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and a number of instances pop out for free, cribbed largely from the definition for Density.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w r) = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (fmap (f .) w) r
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lower (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w r) = fmap ($r) w
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w s) = &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; (extend &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w) s
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w r) = extract w r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reasoning as before about &lt;code&gt;w&lt;/code&gt; as if it were composed of an adjunction &lt;code&gt;f -| g : Hask -&amp;gt; Hask&lt;/code&gt; to build some intuition, we can see:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w a ~ exists r. (w (r -&amp;gt; a), r)
      ~ exists r. (f (g (r -&amp;gt; a)), r)
      ~ exists r. (f (), g (r -&amp;gt; a), r)
      ~ exists r. (f (), f () -&amp;gt; r -&amp;gt; a, r)
      ~ exists r. (f () -&amp;gt; r -&amp;gt; a, f r)
      ~ exists r. (f r -&amp;gt; a, f r)
      ~ &lt;span class=&quot;hljs-type&quot;&gt;Density&lt;/span&gt; f a
      ~ &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f f a
      ~ (f . &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt;) a
      ~ (f . g) a
      ~ w a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The latter few steps require identities established in my &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;second post on Kan extensions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With that we obtain the &quot;remarkable&quot; insight that &lt;code&gt;L ~ IdentityT&lt;/code&gt;, which I suppose is much more obvious when just looking at the type&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; :: w (r -&amp;gt; a) -&amp;gt; r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;L&lt;/span&gt; w a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and seeing the existentially quantified &lt;code&gt;r&lt;/code&gt; as a piece of the environment, being used to build an &lt;code&gt;a&lt;/code&gt;, since there is nothing else we can do with it, except pass it in to each function wrapped by &lt;code&gt;w&lt;/code&gt;! So at first blush, we've gained nothing.&lt;/p&gt;
&lt;p&gt;The key observation is that in one case we would up with something isomorphic to the codensity monad of our right adjoint, while in the other case we would up with the density comonad of our left adjoint. The former is isomorphic to the monad given by our adjunction, while the latter is isomorphic to the comonad, which is, unfortunately, right where we started!&lt;/p&gt;
&lt;h2 id=&quot;in-the-future-all-comonads-are-comonad-transformers&quot;&gt;In The Future All Comonads are Comonad Transformers!&lt;/h2&gt;
&lt;p&gt;Of course, we don't have to just modify a trivial left Kan extension. Let's tweak the &lt;code&gt;Density&lt;/code&gt; comonad of another comonad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f w a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; :: w (f r -&amp;gt; a) -&amp;gt; f r -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f w a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since both arguments will be comonads, and I want this to be a comonad transformer, I'm going to swap the roles of the arguments relative to the definition of &lt;code&gt;CoT w m&lt;/code&gt;. The reason is that &lt;code&gt;D f w&lt;/code&gt; is a Comonad, regardless of the properties of f, so long as &lt;code&gt;w&lt;/code&gt; is a &lt;code&gt;Comonad&lt;/code&gt; This is similar to how &lt;code&gt;Density f&lt;/code&gt; is a Comonad regardless of what &lt;code&gt;f&lt;/code&gt; is, as long as it has kind &lt;code&gt;* -&amp;gt; *&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The implementation of &lt;code&gt;D&lt;/code&gt; is identical to &lt;code&gt;L&lt;/code&gt; above, just as &lt;code&gt;CoT&lt;/code&gt; and &lt;code&gt;Co&lt;/code&gt; share implementations and &lt;code&gt;ContT&lt;/code&gt; and &lt;code&gt;Cont&lt;/code&gt; do.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r) = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (fmap (f .) w) r
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w s) = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (extend &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w) s
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r) = extract w r
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadTrans&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lower (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r) = fmap ($r) w
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But in addition to being able to &lt;code&gt;lower :: D f w a -&amp;gt; w a&lt;/code&gt;, we can also lower to the other comonad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fstD&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f w a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;fstD&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r) = extend (extract w) r

&lt;span class=&quot;hljs-title&quot;&gt;sndD&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f w a -&amp;gt; w a
&lt;span class=&quot;hljs-title&quot;&gt;sndD&lt;/span&gt; = lower
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that if either comonad provides us with a piece of functionality we can exploit it.&lt;/p&gt;
&lt;h2 id=&quot;selling-products&quot;&gt;Selling Products&lt;/h2&gt;
&lt;p&gt;In general Monad products always exist:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; m n a = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runFst&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;runSnd&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return a = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (return a) (return a)
   &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; ma na &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Pair&lt;/span&gt; (ma &amp;gt;&amp;gt;= runFst . f) (na &amp;gt;&amp;gt;= runSnd . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and Comonad coproducts always exist:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getCoproduct&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;left&lt;/span&gt; :: f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; f g a
&lt;span class=&quot;hljs-title&quot;&gt;left&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;right&lt;/span&gt; :: g a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; f g a
&lt;span class=&quot;hljs-title&quot;&gt;right&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;coproduct&lt;/span&gt; :: (f a -&amp;gt; b) -&amp;gt; (g a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; f g a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;coproduct&lt;/span&gt; f g = either f g . getCoproduct
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extend f = &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; . coproduct
    (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; . extend (f . &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;))
    (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; . extend (f . &lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Coproduct&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract = coproduct extract extract
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but Christoph Lüth and Neil Ghani showed that &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.8.3581&quot;&gt;monad coproducts don't always exist&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;On the other hand what we built up above looks a lot like a comonad product!&lt;/p&gt;
&lt;p&gt;Too see that, first we'll note some of the product-like things we can do:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fstD&lt;/code&gt; and &lt;code&gt;sndD&lt;/code&gt; act a lot like &lt;code&gt;fst&lt;/code&gt; and &lt;code&gt;snd&lt;/code&gt;, projecting our parts of our product and it turns out we can &quot;braid&quot; our almost-products, interchanging the left and right hand side.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;braid&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f w a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w f a
&lt;span class=&quot;hljs-title&quot;&gt;braid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r) = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (extend (flip extract) r) w
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(I use scary air-quotes around braid, because it doesn't let us braid them in a categorical sense, as we'll see.)&lt;/p&gt;
&lt;p&gt;After braiding, one of our projections swaps places as we'd expect:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;sndD&lt;/span&gt; (braid (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r)) = &lt;span class=&quot;hljs-comment&quot;&gt;-- by braid def&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sndD&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (extend (flip extract) r) w) = &lt;span class=&quot;hljs-comment&quot;&gt;-- by sndD (and lower) def&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; ($w) (extend (flip extract) r) = &lt;span class=&quot;hljs-comment&quot;&gt;-- extend fmap fusion&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;extend&lt;/span&gt; (($w) . flip extract) r = &lt;span class=&quot;hljs-comment&quot;&gt;-- @unpl&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;extend&lt;/span&gt; (\t -&amp;gt; flip extract t w) r = &lt;span class=&quot;hljs-comment&quot;&gt;-- flip . flip = id&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;extend&lt;/span&gt; (extract w) r = &lt;span class=&quot;hljs-comment&quot;&gt;-- by fstD def&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;fstD&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; w r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we stall when we try to show &lt;code&gt;fstD . braid = sndD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Why is that?&lt;/p&gt;
&lt;h2 id=&quot;a-product-of-an-imperfect-union&quot;&gt;A Product of an Imperfect Union&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/more-on-comonads-as-monad-transformers/&quot;&gt;Last time&lt;/a&gt;, when we inspected &lt;code&gt;CoT w m a&lt;/code&gt; we demonstrated that on one hand given a suitable adjunction &lt;code&gt;f -| g&lt;/code&gt;, such that &lt;code&gt;w = f . g&lt;/code&gt;, &lt;code&gt;Co w ~ Co (f . g) ~ (g . f)&lt;/code&gt;, but on the other &lt;code&gt;CoT w m a&lt;/code&gt; was bigger than &lt;code&gt;g . m . f&lt;/code&gt;, and that if n -| m, then &lt;code&gt;CoT w m a ~ g . m . n . f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course, these two results agree, if you view &lt;code&gt;Co w&lt;/code&gt; as &lt;code&gt;CoT w Identity&lt;/code&gt;, where &lt;code&gt;Identity -| Identity&lt;/code&gt;, since &lt;code&gt;Identity ~ Identity . Identity&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Therefore it should come as no surprise that given &lt;code&gt;w = f . g&lt;/code&gt;, for a suitable adjunction &lt;code&gt;f -| g&lt;/code&gt;, then &lt;code&gt;D w j a&lt;/code&gt; is bigger than &lt;code&gt;f . j . g&lt;/code&gt;. In fact if, &lt;code&gt;j -| k&lt;/code&gt;, then &lt;code&gt;D w j ~ f . j . k . g&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So what is happening is that we have only managed to &quot;break one of our comonads in half&quot;, and &lt;code&gt;D w j a&lt;/code&gt; lets you do 'too much stuff' with the &lt;code&gt;j&lt;/code&gt; portion of the comonad. This keeps us from being symmetric.&lt;/p&gt;
&lt;p&gt;Moreover it turns out to be a bit trickier to build one than to just hand in a &lt;code&gt;w (f a)&lt;/code&gt; or &lt;code&gt;w a&lt;/code&gt; and an &lt;code&gt;f a&lt;/code&gt; to build our product-like construction.&lt;/p&gt;
&lt;p&gt;Even so, exploiting Density &lt;em&gt;was&lt;/em&gt; enough to transform any comonad into a comonad-transformer and to enable us to access the properties of either the comonad we are transforming with, or the comonad that we are transforming.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/a-product-of-an-imperfect-union/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>More on Comonads as Monad Transformers</title><link>https://comonad.com/reader/2011/more-on-comonads-as-monad-transformers/</link><guid isPermaLink="false">https://comonad.com/reader/2011/more-on-comonads-as-monad-transformers/</guid><pubDate>Thu, 30 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 June 2011&lt;/p&gt;&lt;span id=&quot;more-328&quot;&gt;&lt;/span&gt;&lt;p&gt;Last time in &lt;a href=&quot;https://comonad.com/reader/2011/monad-transformers-from-comonads/&quot;&gt;Monad Transformers from Comonads&lt;/a&gt; I showed that given any comonad we can derive the monad-transformer&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m a = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runCoT&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and so demonstrated that there are fewer comonads than monads in Haskell, because while every Comonad gives rise to a Monad transformer, there are Monads that do not like &lt;code&gt;IO&lt;/code&gt;, &lt;code&gt;ST s&lt;/code&gt;, and &lt;code&gt;STM&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I want to elaborate a bit more on this topic.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;Monads from Comonads&lt;/a&gt; we observed that for non-transformer version of &lt;code&gt;CoT&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;under the assumption that &lt;code&gt;w = f . g&lt;/code&gt; for &lt;code&gt;f -| g : Hask -&amp;gt; Hask&lt;/code&gt;, then&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w ~ &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (f . g) ~ g . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This demonstrated that the &lt;code&gt;Co w&lt;/code&gt; is isomorphic to the monad we obtain by composing the adjunction that gave rise to our comonad the other way around.&lt;/p&gt;
&lt;p&gt;But what about &lt;code&gt;CoT&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Sadly &lt;code&gt;CoT&lt;/code&gt; is a bit bigger.&lt;/p&gt;
&lt;p&gt;We can see by first starting to apply the same treatment that we gave &lt;code&gt;Co&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. w (a -&amp;gt; m r) -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. f (g (a -&amp;gt; m r)) -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. f (f() -&amp;gt; a -&amp;gt; m r) -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. f (a -&amp;gt; f () -&amp;gt; m r) -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; f () -&amp;gt; m r, f ()) -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; f () -&amp;gt; m r) -&amp;gt; f () -&amp;gt; m r
    ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; g (m r)) -&amp;gt; g (m r)
    ~ &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (g . m) a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(I'm using &lt;code&gt;.&lt;/code&gt; to represent &lt;code&gt;Compose&lt;/code&gt; for readability.)&lt;/p&gt;
&lt;p&gt;But we've seen before that &lt;code&gt;Codensity g a&lt;/code&gt; is in a sense bigger than &lt;code&gt;g a&lt;/code&gt;, since given an Adjunction &lt;code&gt;f -| g&lt;/code&gt;, &lt;code&gt;Codensity g a ~ (g . f) a&lt;/code&gt;, &lt;strong&gt;not&lt;/strong&gt; &lt;code&gt;g a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Moreover can compose adjunctions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  unit   = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . leftAdjunct (leftAdjunct &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt;)
  counit = rightAdjunct (rightAdjunct getCompose) . getCompose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So if &lt;code&gt;n -| m&lt;/code&gt;, then we can see that &lt;code&gt;Codensity (g . m) a ~ g . m . n . f&lt;/code&gt;, rather than the smaller &lt;code&gt;g . m . f&lt;/code&gt;, which we can obtain using &lt;code&gt;AdjointT f g m&lt;/code&gt; from &lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.8.0/doc/html/Control-Monad-Trans-Adjoint.html&quot;&gt;Control.Monad.Trans.Adjoint&lt;/a&gt; in &lt;a href=&quot;https://hackage.haskell.org/package/adjunctions&quot;&gt;adjunctions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;CoT&lt;/code&gt; isn't the smallest monad transformer that would be given by an adjunction.&lt;/p&gt;
&lt;p&gt;In fact, it is isomorphic to &lt;code&gt;AdjointT f g (Codensity m) a&lt;/code&gt; instead of &lt;code&gt;AdjointT f g m a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Sadly, there doesn't appear to be a general purpose construction of the smaller transformer just given an unseparated &lt;code&gt;w = f . g&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/more-on-comonads-as-monad-transformers/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monad Transformers from Comonads</title><link>https://comonad.com/reader/2011/monad-transformers-from-comonads/</link><guid isPermaLink="false">https://comonad.com/reader/2011/monad-transformers-from-comonads/</guid><pubDate>Tue, 28 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 28 June 2011&lt;/p&gt;&lt;span id=&quot;more-321&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;Last time&lt;/a&gt;, I showed that we can transform any Comonad in Haskell into a Monad in Haskell.&lt;/p&gt;
&lt;p&gt;Today, I'll show that we can go one step further and derive a monad transformer from any comonad!&lt;/p&gt;
&lt;h2 id=&quot;a-comonad-to-monad-transformer-transformer&quot;&gt;A Comonad to Monad-Transformer Transformer&lt;/h2&gt;
&lt;p&gt;Given&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m a = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runCoT&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can easily embed the type of the previous &lt;code&gt;Co&lt;/code&gt; and create a smart constructor and deconstructor in the style of the MTL.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;co&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. w (a -&amp;gt; r) -&amp;gt; r) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a
&lt;span class=&quot;hljs-title&quot;&gt;co&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; . f . fmap (fmap runIdentity))

&lt;span class=&quot;hljs-title&quot;&gt;runCo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a -&amp;gt; w (a -&amp;gt; r) -&amp;gt; r
&lt;span class=&quot;hljs-title&quot;&gt;runCo&lt;/span&gt; m = runIdentity . runCoT m . fmap (fmap &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact, as with between Cont and ContT, none of the major instances even change!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w) = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (w . fmap (. f))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Apply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  mf &amp;lt; .&amp;gt; ma = mf &amp;gt;&amp;gt;- \f -&amp;gt; fmap f ma
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; k &amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (k . extend (\wa a -&amp;gt; runCoT (f a) wa))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  pure a = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (`extract` a)
  mf &amp;lt; *&amp;gt; ma = mf &amp;gt;&amp;gt;= \f -&amp;gt; fmap f ma
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (`extract` a)
  &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; k &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (k . extend (\wa a -&amp;gt; runCoT (f a) wa))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use CoT as a Monad transformer, or lift IO actions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  lift m = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (extract . fmap (m &amp;gt;&amp;gt;=))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  liftIO = lift . liftIO
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(This monad transformer is available in my &lt;a href=&quot;https://hackage.haskell.org/package/kan-extensions&quot;&gt;kan-extensions&lt;/a&gt; package as of 1.9.0 on hackage.)&lt;/p&gt;
&lt;p&gt;And as before we can lift and lower CoKleisli arrows, although the results are monadic when lowered.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;liftCoT0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. w a -&amp;gt; s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m s
&lt;span class=&quot;hljs-title&quot;&gt;liftCoT0&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (extract &amp;lt; *&amp;gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;lowerCoT0&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m s -&amp;gt; w a -&amp;gt; m s
&lt;span class=&quot;hljs-title&quot;&gt;lowerCoT0&lt;/span&gt; m = runCoT m . (return &amp;lt; $)

&lt;span class=&quot;hljs-title&quot;&gt;lowerCo0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w s -&amp;gt; w a -&amp;gt; s
&lt;span class=&quot;hljs-title&quot;&gt;lowerCo0&lt;/span&gt; m = runIdentity . runCoT m . (return &amp;lt; $)

&lt;span class=&quot;hljs-title&quot;&gt;liftCoT1&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. w a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m ()
&lt;span class=&quot;hljs-title&quot;&gt;liftCoT1&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (`f` ())

&lt;span class=&quot;hljs-title&quot;&gt;lowerCoT1&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m () -&amp;gt; w a -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;lowerCoT1&lt;/span&gt; m = runCoT m . fmap (const . return)

&lt;span class=&quot;hljs-title&quot;&gt;lowerCo1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w () -&amp;gt; w a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lowerCo1&lt;/span&gt; m = runIdentity . runCoT m . fmap (const . return)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we could mean the MonadFoo instance derived from its comonadic equivalent or from the one we wrap as a monad transformer, we choose to default to the one from the monad, but we can still provide the lifted comonadic actions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;posW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadStore&lt;/span&gt; s w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m s
&lt;span class=&quot;hljs-title&quot;&gt;posW&lt;/span&gt; = liftCoT0 pos

&lt;span class=&quot;hljs-title&quot;&gt;peekW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadStore&lt;/span&gt; s w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; s -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m ()
&lt;span class=&quot;hljs-title&quot;&gt;peekW&lt;/span&gt; s = liftCoT1 (peek s)

&lt;span class=&quot;hljs-title&quot;&gt;peeksW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadStore&lt;/span&gt; s w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; (s -&amp;gt; s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m ()
&lt;span class=&quot;hljs-title&quot;&gt;peeksW&lt;/span&gt; f = liftCoT1 (peeks f)

&lt;span class=&quot;hljs-title&quot;&gt;askW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadEnv&lt;/span&gt; e w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m e
&lt;span class=&quot;hljs-title&quot;&gt;askW&lt;/span&gt; = liftCoT0 (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt;.ask)

&lt;span class=&quot;hljs-title&quot;&gt;asksW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadEnv&lt;/span&gt; e w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; (e -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m a
&lt;span class=&quot;hljs-title&quot;&gt;asksW&lt;/span&gt; f = liftCoT0 (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt;.asks f)

&lt;span class=&quot;hljs-title&quot;&gt;traceW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;ComonadTraced&lt;/span&gt; e w, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; e -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; w m ()
&lt;span class=&quot;hljs-title&quot;&gt;traceW&lt;/span&gt; e = liftCoT1 (&lt;span class=&quot;hljs-type&quot;&gt;Traced&lt;/span&gt;.trace e)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we just lift the monadic actions as usual:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; e (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  ask = lift &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt;.ask
  local f m = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (local f . runCoT m)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  get = lift get
  put = lift . put
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadWriter&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadWriter&lt;/span&gt; e (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  tell = lift . tell
  pass m = &lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; (pass . runCoT m . fmap aug) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
    aug f (a,e) = liftM (\r -&amp;gt; (r,e)) (f a)
  listen = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;Control.Monad.Co.listen: TODO&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadError&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadError&lt;/span&gt; e (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  throwError = lift . throwError
  catchError = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;Control.Monad.Co.catchError: TODO&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadCont&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadCont&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;CoT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  callCC = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;Control.Monad.Co.callCC: TODO&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I welcome help working through the missing methods above.&lt;/p&gt;
&lt;p&gt;This should go a long way towards showing the fact that there are strictly fewer comonads than monads in Haskell, and of course that there are no analogues to IO, STM and ST s in the world of Haskell comonads!&lt;/p&gt;
&lt;p&gt;Every comonad gives you a monad-transformer, but not every monad is a monad transformer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/monad-transformers-from-comonads/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monads from Comonads</title><link>https://comonad.com/reader/2011/monads-from-comonads/</link><guid isPermaLink="false">https://comonad.com/reader/2011/monads-from-comonads/</guid><pubDate>Mon, 27 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 27 June 2011&lt;/p&gt;&lt;span id=&quot;more-291&quot;&gt;&lt;/span&gt;&lt;p&gt;Today I'll show that you can derive a &lt;code&gt;Monad&lt;/code&gt; from any old &lt;code&gt;Comonad&lt;/code&gt; you have lying around.&lt;/p&gt;
&lt;p&gt;But first, we'll need to take a bit of a bit of a detour.&lt;/p&gt;
&lt;h2 id=&quot;a-monad-sandwich&quot;&gt;A Monad Sandwich&lt;/h2&gt;
&lt;p&gt;We'll need the definition of an &lt;a href=&quot;http://en.wikipedia.org/wiki/Adjoint_functors&quot;&gt;adjunction&lt;/a&gt; on the category of Haskell types, which we can strip down and borrow from my &lt;a href=&quot;https://hackage.haskell.org/package/adjunctions&quot;&gt;adjunctions&lt;/a&gt; package.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;u&lt;/span&gt;) =&amp;gt;
         &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f u | f -&amp;gt; u, u -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    leftAdjunct :: (f a -&amp;gt; b) -&amp;gt; a -&amp;gt; u b
    rightAdjunct :: (a -&amp;gt; u b) -&amp;gt; f a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we can define our Adjunction by defining leftAdjunct and rightAdjunct, such that they witness an isomorphism from &lt;code&gt;(f a -&amp;gt; b)&lt;/code&gt; to &lt;code&gt;(a -&amp;gt; u b)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Every &lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.0.0/doc/html/Data-Functor-Adjunction.html&quot;&gt;Adjunction&lt;/a&gt; &lt;code&gt;F -| G : C -&amp;gt; D&lt;/code&gt;, gives rise to a monad GF on D and a Comonad FG on C.&lt;/p&gt;
&lt;p&gt;In addition to this, you can sandwich an additional monad M on C in between GF to give a monad GMF on D:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.0.0/doc/html/Control-Monad-Trans-Adjoint.html&quot;&gt;Control.Monad.Trans.Adjoint&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and you can sandwich a comonad W on D in between F and G to yield the comonad FWG on C:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.0.0/doc/html/Control-Comonad-Trans-Adjoint.html&quot;&gt;Control.Comonad.Trans.Adjoint&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-contravariant-comonad-sandwich&quot;&gt;A Contravariant Comonad Sandwich&lt;/h2&gt;
&lt;p&gt;As was first shown to me me by Derek Elkins, this construction works even when you C is not the category of Haskell types!&lt;/p&gt;
&lt;p&gt;Consider the &lt;a href=&quot;https://hackage.haskell.org/packages/archive/contravariant/0.1.2/doc/html/Data-Functor-Contravariant.html&quot;&gt;Contravariant&lt;/a&gt; functor &lt;code&gt;Op r&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; a b = &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getOp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  contramap f g = &lt;span class=&quot;hljs-type&quot;&gt;Op&lt;/span&gt; (getOp g . f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can view &lt;code&gt;Op r&lt;/code&gt; as a functor from &lt;code&gt;Hask^op -&amp;gt; Hask&lt;/code&gt; or as one from &lt;code&gt;Hask -&amp;gt; Hask^op&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can define a notion of a contravariant adjunction &lt;code&gt;F -| G : Hask^op -&amp;gt; Hask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.0.0/doc/html/Data-Functor-Contravariant-Adjunction.html&quot;&gt;Data.Functor.Contravariant.Adjunction&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Corepresentable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt;
       &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    leftAdjunct :: (b -&amp;gt; f a) -&amp;gt; a -&amp;gt; g b
    rightAdjunct :: (a -&amp;gt; g b) -&amp;gt; b -&amp;gt; f a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where, now, &lt;code&gt;leftAdjunct&lt;/code&gt; and &lt;code&gt;rightAdjunct&lt;/code&gt; witness the isomorphism from &lt;code&gt;(f a &amp;lt; - b)&lt;/code&gt; to &lt;code&gt;(a -&amp;gt; g b)&lt;/code&gt;, which means once you flip the arrow around both seem to be going the same way. Ultimately any contravariant adjunction on Hask is comprised of two isomorphic functors, each self-adjoint.&lt;/p&gt;
&lt;p&gt;This gives rise to one notion of a comonad-to-monad transformer!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hackage.haskell.org/packages/archive/adjunctions/1.0.0/doc/html/Control-Monad-Trans-Contravariant-Adjoint.html&quot;&gt;Control.Monad.Trans.Contravariant.Adjoint&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But we can we do better?&lt;/p&gt;
&lt;h2 id=&quot;an-end-as-the-means&quot;&gt;An End as the Means&lt;/h2&gt;
&lt;p&gt;First, some boilerplate.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE Rank2Types, FlexibleInstances, FlexibleContexts, MultiParamTypeClasses, UndecidableInstances #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad.Store.Class
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad.Env.Class &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Env
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad.Traced.Class &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Traced
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Reader.Class
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Writer.Class
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.State.Class
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Functor.Bind
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our new comonad to monad transformer is given by&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runCo&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we've done is added a quantifier to prevent the use of the type &lt;em&gt;r&lt;/em&gt;, as we did when describing &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.1/doc/html/Control-Monad-Codensity.html&quot;&gt;&lt;code&gt;Codensity&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.1/doc/html/Data-Functor-KanExtension.html&quot;&gt;&lt;code&gt;Ran&lt;/code&gt;&lt;/a&gt;, categorically we've taken some kind of &lt;a href=&quot;http://en.wikipedia.org/wiki/End_(category_theory)&quot;&gt;end&lt;/a&gt;. This idea came to me after an observation was made by Russell O'Connor that &lt;code&gt;Conts (Store s) a&lt;/code&gt; was pretty close to a continuation passing style version of &lt;code&gt;State s&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, we can start spitting out instances for this type.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w) = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (w . fmap (. f))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return a = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (`extract` a)
   &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; k &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (k .extend (\wa a -&amp;gt; runCo (f a) wa))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Applicative&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   mf &amp;lt; *&amp;gt; ma = mf &amp;gt;&amp;gt;= \f -&amp;gt; fmap f ma
   pure a = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (`extract` a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my break-out of category-extras, I've split off the semigroupoid structure of Kleisli-, co-Kleisli-, and static- arrow composition as &lt;code&gt;Bind&lt;/code&gt;, &lt;code&gt;Extend&lt;/code&gt; and &lt;code&gt;Apply&lt;/code&gt; respectively, so we can make use of slightly less structure and get slightly less structure in turn:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; k &amp;gt;&amp;gt;- f = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (k .extend (\wa a -&amp;gt; runCo (f a) wa))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Apply&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   mf &amp;lt; .&amp;gt; ma = mf &amp;gt;&amp;gt;- \f -&amp;gt; fmap f ma
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;from-comonad-transformers-to-the-mtl&quot;&gt;From comonad-transformers to the mtl&lt;/h2&gt;
&lt;p&gt;We can look at how this transforms some particular comonads.&lt;/p&gt;
&lt;p&gt;The comonadic version of &lt;a href=&quot;https://hackage.haskell.org/packages/archive/mtl/2.0.1.0/doc/html/Control-Monad-State-Lazy.html&quot;&gt;&lt;code&gt;State&lt;/code&gt;&lt;/a&gt; is &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonad-transformers/1.7/doc/html/Control-Comonad-Trans-Store-Lazy.html&quot;&gt;&lt;code&gt;Store&lt;/code&gt;&lt;/a&gt;. Looking at &lt;code&gt;Co (Store s) a&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; s) a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. ((s -&amp;gt; a -&amp;gt; r, s) -&amp;gt; r)
         ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (s -&amp;gt; a -&amp;gt; r) -&amp;gt; s -&amp;gt; r
         ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; s -&amp;gt; r) -&amp;gt; s -&amp;gt; r
         ~ &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; ((-&amp;gt;)s) a
         ~ &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt; s a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives rise to a leap of intuition that we'll motivate further below:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadStore&lt;/span&gt; s m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   get = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (\w -&amp;gt; extract w (pos w))
   put s = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (\w -&amp;gt; peek s w ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly this breaks down a little for &lt;code&gt;Writer&lt;/code&gt; and &lt;code&gt;Reader&lt;/code&gt; as the &lt;code&gt;mtl&lt;/code&gt; unfortunately has historically included a bunch of extra baggage in these classes. In particular, in reader, the notion of &lt;code&gt;local&lt;/code&gt; isn't always available, blocking some otherwise perfectly good &lt;code&gt;MonadReader&lt;/code&gt; instances, and I've chosen not to repeat this mistake in &lt;code&gt;comonad-transformers&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadEnv&lt;/span&gt; e m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; e (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   ask = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (\w -&amp;gt; extract w (&lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt;.ask w))
   local = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;local&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ideally, local belongs in a subclass of &lt;code&gt;MonadReader&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; e m | m -&amp;gt; e &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   ask :: m a -&amp;gt; e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; e m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadLocal&lt;/span&gt; e m | m -&amp;gt; e &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   local :: (e -&amp;gt; e) -&amp;gt; m a -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly there is a lot of baggage in the &lt;code&gt;MonadWriter&lt;/code&gt;. The &lt;code&gt;Monoid&lt;/code&gt; constraint isnt necessary for the class itself, just for most instances, and the &lt;code&gt;listen&lt;/code&gt; and &lt;code&gt;pass&lt;/code&gt; members should be a member of a more restricted subclass as well to admit some missing &lt;code&gt;MonadWriter&lt;/code&gt; instances, but we can at least provide the notion of tell that is critical to &lt;code&gt;Writer&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;ComonadTraced&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadWriter&lt;/span&gt; e (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   tell m = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (\w -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Traced&lt;/span&gt;.trace m w ())
   listen = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;listen&quot;&lt;/span&gt;
   pass = error &lt;span class=&quot;hljs-string&quot;&gt;&quot;pass&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But given the split out&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadWriter&lt;/span&gt; e m | m -&amp;gt; e &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    tell :: e -&amp;gt; m ()
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadWriter&lt;/span&gt; e m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadListen&lt;/span&gt; e m | m -&amp;gt; e
    listen :: m a -&amp;gt; m (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;)
    pass :: m (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt;) -&amp;gt; m a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could provide this functionality more robustly. (There is a similar subset of &lt;code&gt;Comonad&lt;/code&gt;s that can provide listen and pass analogues.)&lt;/p&gt;
&lt;p&gt;While I am now the maintainer of the mtl, I can't really justify making the above corrections to the class hierarchy at this time. They would theoretically break a lot of code. I would be curious to see how much code would break in practice though.&lt;/p&gt;
&lt;h2 id=&quot;combinators-please&quot;&gt;Combinators Please!&lt;/h2&gt;
&lt;p&gt;There is a recurring pattern in the above code, so we can also improve this construction by providing some automatic lifting combinators that take certain cokleisli arrows and give us monadic values&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lift0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. w a -&amp;gt; s) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w s
&lt;span class=&quot;hljs-title&quot;&gt;lift0&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (extract &amp;lt; *&amp;gt; f)

&lt;span class=&quot;hljs-title&quot;&gt;lift1&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. w a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w ()
&lt;span class=&quot;hljs-title&quot;&gt;lift1&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; (`f` ())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;along with their inverses&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lower0&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w s -&amp;gt; w a -&amp;gt; s
&lt;span class=&quot;hljs-title&quot;&gt;lower0&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; f) w = f (id &amp;lt; $ w)

&lt;span class=&quot;hljs-title&quot;&gt;lower1&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w () -&amp;gt; w a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lower1&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; f) w = f (fmap const w)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(The proofs that these are inverses are quite hairy, and lean heavily on parametricity.)&lt;/p&gt;
&lt;p&gt;Then in the above, the code simplifies to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;get&lt;/span&gt; = lift0 pos
&lt;span class=&quot;hljs-title&quot;&gt;put&lt;/span&gt; s = lift1 (peek s)
&lt;span class=&quot;hljs-title&quot;&gt;ask&lt;/span&gt; = lift0 &lt;span class=&quot;hljs-type&quot;&gt;Env&lt;/span&gt;.ask
&lt;span class=&quot;hljs-title&quot;&gt;tell&lt;/span&gt; s = lift1 (tell s)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;co-density&quot;&gt;Co-Density?&lt;/h2&gt;
&lt;p&gt;Co and Codensity are closely related.&lt;/p&gt;
&lt;p&gt;Given any Comonad W, it is given rise to by the composition FG for some adjunction &lt;code&gt;F -| G : Hask -&amp;gt; C&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Considering only the case where &lt;code&gt;C = Hask&lt;/code&gt; for now, we can find that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (f (g (a -&amp;gt; r)) -&amp;gt; r).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;f -| g&lt;/code&gt;, we know that &lt;code&gt;g&lt;/code&gt; is &lt;code&gt;Representable&lt;/code&gt; by &lt;code&gt;f ()&lt;/code&gt;, as witnessed by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;tabulateAdjunction&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f u =&amp;gt; (f () -&amp;gt; b) -&amp;gt; u b
&lt;span class=&quot;hljs-title&quot;&gt;tabulateAdjunction&lt;/span&gt; f = leftAdjunct f ()

&lt;span class=&quot;hljs-title&quot;&gt;indexAdjunction&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f u =&amp;gt; u b -&amp;gt; f a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;indexAdjunction&lt;/span&gt; = rightAdjunct . const
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;therefore&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ f (g (a -&amp;gt; r)) -&amp;gt; r ~ f (f () -&amp;gt; a -&amp;gt; r) -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;em&gt;f&lt;/em&gt; is a left adjoint functor, &lt;code&gt;f a ~ (a, f ())&lt;/code&gt; by Sjoerd Visscher's elegant little &lt;code&gt;split&lt;/code&gt; combinator:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;split&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f u =&amp;gt; f a -&amp;gt; (a, f ())
&lt;span class=&quot;hljs-title&quot;&gt;split&lt;/span&gt; = rightAdjunct (flip leftAdjunct () . (,))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which has the simple inverse&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsplit&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; a -&amp;gt; f () -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;unsplit&lt;/span&gt; a = fmap (const a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so we can apply that to our argument:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. f (f () -&amp;gt; a -&amp;gt; r) -&amp;gt; r ~
   &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (f () -&amp;gt; a -&amp;gt; r, f ()) -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and curry to obtain&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (f () -&amp;gt; a -&amp;gt; r) -&amp;gt; f () -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and swap the arguments&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; f () -&amp;gt; r) -&amp;gt; f () -&amp;gt; r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then we can tabulate the two subtypes of the form (f () -&amp;gt; r)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; g r) -&amp;gt; g r
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and so we find that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Co&lt;/span&gt; w a ~ &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; g a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; g a ~ &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g g a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but we showed back in my second article on Kan extensions that given f -| g that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g g a ~ g (f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;Co w ~ Co (f . g) ~ (g . f)&lt;/code&gt;, the monad given rise to by composing our adjunction the other way!&lt;/p&gt;
&lt;h2 id=&quot;comonads-from-monads&quot;&gt;Comonads from Monads?&lt;/h2&gt;
&lt;p&gt;Now, given all this you might ask&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is there is a similar construction that lets you build a comonad out of a monad?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sadly, it seems the answer &lt;strong&gt;in Haskell&lt;/strong&gt; is no.&lt;/p&gt;
&lt;p&gt;Any adjunction from &lt;code&gt;Hask -&amp;gt; Hask^op&lt;/code&gt; would require two functions&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;DualContravariantAdjunction&lt;/span&gt; f g &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    leftAdjunct :: (f a -&amp;gt; b) -&amp;gt; g b -&amp;gt; a
    rightAdjunct :: (g b -&amp;gt; a) -&amp;gt; f a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;strong&gt;both functors are contravariant&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Surmounting the intuitionistic impossibility of this, then given any such adjunction, there would be a nice coend we could take, letting us sandwich any &lt;code&gt;Monad&lt;/code&gt; in the middle as we did above.&lt;/p&gt;
&lt;p&gt;There does exist one such very boring Contravariant Functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;absurdity&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;absurdity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; a) = absurdity a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Contravariant&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   contramap f (&lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; (contramap f &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DualContravariantAdjunction&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    leftAdjunct _ = absurdity
    rightAdjunct _ = absurdity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can safely sandwich IO within this adjunction from &lt;code&gt;Hask -&amp;gt; Hask^op&lt;/code&gt; to obtain a comonad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; m a = &lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runSilly&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Absurd&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Extend&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    extend f (&lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; m) = absurdity m
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    extract (&lt;span class=&quot;hljs-type&quot;&gt;Silly&lt;/span&gt; m) = absurdity m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But for any more interesting such type that actually lets us get at its contents, we would be able to derive a circuitous path to &lt;code&gt;unsafePerformIO&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;unsafePerformIO&lt;/code&gt; should not be constructible without knowing &lt;code&gt;IO&lt;/code&gt; specifics, no &lt;strong&gt;useful&lt;/strong&gt; &lt;code&gt;DualContravariantAdjunction&lt;/code&gt;s should exist.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/monads-from-comonads/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Free Monads for Less (Part 3 of 3): Yielding IO</title><link>https://comonad.com/reader/2011/free-monads-for-less-3/</link><guid isPermaLink="false">https://comonad.com/reader/2011/free-monads-for-less-3/</guid><pubDate>Fri, 24 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 24 June 2011&lt;/p&gt;&lt;span id=&quot;more-251&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less-2/&quot;&gt;Last time&lt;/a&gt;, I said that I was going to put our cheap new free monad to work, so let's give it a shot.&lt;/p&gt;
&lt;h2 id=&quot;yield-for-less&quot;&gt;Yield for Less&lt;/h2&gt;
&lt;p&gt;Last month at &lt;a href=&quot;http://www.pps.jussieu.fr/~saurin/tpdc2011/&quot;&gt;TPDC 2011&lt;/a&gt;, Roshan James and Amr Sabry presented &lt;a href=&quot;http://parametricity.net/dropbox/yield.subc.pdf&quot;&gt;Yield: Mainstream Delimited Continuations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Without calling it such they worked with the free monad of the indexed store comonad. Ignoring the comonad, and just looking at the functor we can see that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; i o r = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) o&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;admits the operation&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; y =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; y i o | y -&amp;gt; i o &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   yield :: o -&amp;gt; y i
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;) i o &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   yield = &lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The free monad of &lt;code&gt;Store i o&lt;/code&gt; is a nice model for asymmetric coroutines.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; i o = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Store&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;liftFree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;liftFree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; . fmap &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; y i o =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt;) i o &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   yield = liftFree . yield
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With its &lt;code&gt;Monad&lt;/code&gt;, you can write computations like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; o =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; () o ()
&lt;span class=&quot;hljs-title&quot;&gt;foo&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
   yield &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
   yield &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
   yield &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or to streamline one of James and Sabry's examples&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;walk&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; f =&amp;gt; f o -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; i o (f i)
&lt;span class=&quot;hljs-title&quot;&gt;walk&lt;/span&gt; = traverse yield
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is an asymmetric coroutine that yields each of the elements in a traversable container in turn, replacing them with the responses from whatever is driving the coroutine.&lt;/p&gt;
&lt;p&gt;James and Sabry called this the naive frame grabbing implementation. It is inefficient for the same reasons that we discussed before about retraversing the common trunk in free monads in general. Note that the unchanging trunk here isn't the data structure that we're traversing, but instead the chain of &lt;code&gt;Store i o&lt;/code&gt; actions we took to get to the current instruction.&lt;/p&gt;
&lt;p&gt;James and Sabry then proceeded to optimize it by hitting it with &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/Control-Monad-Codensity.html&quot;&gt;Codensity&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Iterator&lt;/span&gt; i o = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Yield&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt;) i o &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   yield = liftCodensity . yield
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we've now seen that we can get away with something smaller and get the same benefits.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;liftF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;liftF&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp kf -&amp;gt; kf (fmap kp f))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; y i o =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yieldable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;y&lt;/span&gt;) i o &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   yield = liftF . yield
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Flattened, and with the store untupled the new optimized representation looks like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Iterator&lt;/span&gt; i o a = &lt;span class=&quot;hljs-type&quot;&gt;Iterator&lt;/span&gt;&lt;/span&gt;
  { runIterator ::
    &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; r) -&amp;gt; (o -&amp;gt; (i -&amp;gt; r) -&amp;gt; r) -&amp;gt; r)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and provides the same performance improvements for asymmetric coroutines as the &lt;code&gt;Codensity&lt;/code&gt; version, used by James and Sabry, which would flatten to the much larger and less satisfying:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RSIterator&lt;/span&gt; i o a = &lt;span class=&quot;hljs-type&quot;&gt;RSIterator&lt;/span&gt;&lt;/span&gt;
    { runRSIterator :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r.
          (a -&amp;gt; (o -&amp;gt; (i -&amp;gt; r) -&amp;gt; r) -&amp;gt; r)
             -&amp;gt; (o -&amp;gt; (i -&amp;gt; r) -&amp;gt; r) -&amp;gt; r
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;They proceed to give an encoding of delimited continuations into this type and vice versa, but the rest of their material is of no further use to us here.&lt;/p&gt;
&lt;p&gt;As an aside the performance benefits of encoding Oleg's &lt;a href=&quot;http://okmij.org/ftp/Streams.html&quot;&gt;iteratees&lt;/a&gt; in &lt;a href=&quot;https://hackage.haskell.org/packages/archive/iteratee/0.8.5.0/doc/html/Data-Iteratee-Base.html&quot;&gt;continuation passing style&lt;/a&gt; arise for much the same reason. The resuting encoding is a right Kan extension!&lt;/p&gt;
&lt;h2 id=&quot;who-needs-the-realworld&quot;&gt;Who Needs the RealWorld?&lt;/h2&gt;
&lt;p&gt;As &lt;a href=&quot;http://twitter.com/#!/runarorama/status/83570792704638976&quot;&gt;Runar recently tweeted&lt;/a&gt;, we have put this to good use here at &lt;a href=&quot;https://www.capitaliq.com/home/what-we-offer/how-you-can-get-it/clarifi.aspx&quot;&gt;ClariFI&lt;/a&gt;. (&lt;strong&gt;Yes&lt;/strong&gt;, we are hiring! If the contents of my blog make sense to you then &lt;a href=&quot;mailto:ekmett@gmail.com&quot;&gt;email me&lt;/a&gt; and let's talk.)&lt;/p&gt;
&lt;p&gt;At ClariFI have a strongly typed functional language that bears a strong resemblance to Haskell with &lt;a href=&quot;http://www.haskell.org/haskellwiki/Rank-N_types&quot;&gt;rank-n types&lt;/a&gt; and a number of other interesting type system features that are particularly suited to our problem domain.&lt;/p&gt;
&lt;p&gt;However, as with Haskell, we needed a story for how to deal with &lt;code&gt;IO&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, &lt;a href=&quot;http://www.haskell.org/ghc/&quot;&gt;GHC&lt;/a&gt; models &lt;a href=&quot;http://www.haskell.org/ghc/docs/6.2/html/libraries/base/GHC.IOBase.html&quot;&gt;IO&lt;/a&gt; with the type&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a =&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt;# &lt;span class=&quot;hljs-type&quot;&gt;RealWorld&lt;/span&gt; -&amp;gt; (# a, &lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt;# &lt;span class=&quot;hljs-type&quot;&gt;RealWorld&lt;/span&gt; #))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where they model &lt;code&gt;IO&lt;/code&gt; by working in a strict state monad, passing around a real world that they promise not to mutate or copy. (In practice, the world is passed around as a 0-byte token.&lt;/p&gt;
&lt;p&gt;This is somewhat problematic semantically, for a number of reasons.&lt;/p&gt;
&lt;p&gt;First, There is always the risk of copying it or plumbing it through backwards, so we carefully hide the &lt;code&gt;State# RealWorld&lt;/code&gt; from the end user. So this model really wants some notion of uniqueness or linear typing to render it perfectly safe. Heck, the entire &lt;a href=&quot;http://en.wikipedia.org/wiki/Clean_(programming_language)&quot;&gt;Clean&lt;/a&gt; language arose from just trying to address this concern.&lt;/p&gt;
&lt;p&gt;Second, you don't &lt;strong&gt;really&lt;/strong&gt; get to pass the real world around! We have multiple cores working these days. Stuff is happening in the back end, and as much as you might want it to be, your program isn't responsible for everything that happens in the &lt;code&gt;RealWorld&lt;/code&gt;!.&lt;/p&gt;
&lt;p&gt;Third, if in some sense all bottoms are the same, then &lt;code&gt;forever (putStrLn &quot;Hello World&quot;)&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; are the same in that sense, despite the slew of side-effects that arise from the first one. Now, in Haskell you are allowed to catch some bottoms in the IO monad, and thereby escape from certain doom, but it is still a reasonable objection.&lt;/p&gt;
&lt;p&gt;One alternate model for talking about &lt;code&gt;IO&lt;/code&gt; is to view it as a free monad of some set of operations. This approach was taken by Wouter Swierstra's Functional Pearl: &lt;a href=&quot;http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf&quot;&gt;Data Types a la Carte&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can then supply some sort of external interpreter that pumps that tree structure, performing the individual actions.&lt;/p&gt;
&lt;p&gt;This is unsatisfying because of two things:&lt;/p&gt;
&lt;p&gt;First, the performance is abysmal using the common ADT encoding of a free monad. Janis Voigtländer of course showed, that this can be rectified by using the &lt;code&gt;Codensity&lt;/code&gt; monad.&lt;/p&gt;
&lt;p&gt;Second, the set of &lt;code&gt;FFI&lt;/code&gt; operations is closed.&lt;/p&gt;
&lt;p&gt;What we've done instead is to define our primitive &lt;code&gt;IO&lt;/code&gt; actions externally as some &lt;code&gt;FFI&lt;/code&gt; type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FFI&lt;/span&gt; o i &lt;span class=&quot;hljs-comment&quot;&gt;-- external, side-effecting computation taking o, returning i&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In practice, these are obtained by reflection by our &lt;code&gt;foreign import&lt;/code&gt; statements since we run in the JVM.&lt;/p&gt;
&lt;p&gt;Then we looked at the free monad of&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;OI&lt;/span&gt; a = forall o i. &lt;span class=&quot;hljs-type&quot;&gt;OI&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FFI&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt;) o (&lt;span class=&quot;hljs-title&quot;&gt;i&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;OI&lt;/code&gt; is the indexed store comonad used as the building block above, yielding arguments to &lt;code&gt;FFI&lt;/code&gt; of type &lt;em&gt;o&lt;/em&gt;, and representing a computation that would resume with a value of type &lt;em&gt;i&lt;/em&gt; to obtain a result of type &lt;em&gt;a&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In some sense this yields a more useful notion than Richard Kieburtz's novel, but largely unimplementable, &lt;code&gt;OI&lt;/code&gt; comonad from &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.45.4741&amp;rep=rep1&amp;type=ps&quot;&gt;Codata and Comonads in Haskell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Flattening &lt;code&gt;Free OI&lt;/code&gt; would yield the naive&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- data FIO a where&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--    Return :: a -&amp;gt; FIO a&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;--    FIO :: FFI o i -&amp;gt; o -&amp;gt; (i -&amp;gt; FIO a) -&amp;gt; FIO a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which would be interpreted by the runtime system.&lt;/p&gt;
&lt;p&gt;But once we've converted to our Church-encoded Free monad and flattened we obtain:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/span&gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r. (a -&amp;gt; r) -&amp;gt;
                 (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; i o. &lt;span class=&quot;hljs-type&quot;&gt;FFI&lt;/span&gt; o i -&amp;gt; o -&amp;gt; (i -&amp;gt; r) -&amp;gt; r) -&amp;gt;
                 r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with the &lt;code&gt;Functor&lt;/code&gt; and &lt;code&gt;Monad&lt;/code&gt; instances defined above.&lt;/p&gt;
&lt;p&gt;This then gives us a number of choices on how we implement the runtime system:&lt;/p&gt;
&lt;p&gt;We can use the machinery described earlier to convert from &lt;code&gt;IO a&lt;/code&gt; to &lt;code&gt;Free OI a&lt;/code&gt; or &lt;code&gt;FIO a&lt;/code&gt;, and then have the runtime system pattern match on that structure on our main method, taking the &lt;code&gt;FFI&lt;/code&gt; actions and their arguments and passing the results in to the language, or we can invert control, and implement things more directly by just defining&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;FFI&lt;/span&gt; = (-&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;while letting the &lt;code&gt;FFI&lt;/code&gt;'d methods have side-effects, and then defining&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unsafePerformIO&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;unsafePerformIO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; m) = m id (\ oi o ir -&amp;gt; ir (oi o))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But regardless of how &lt;code&gt;FFI&lt;/code&gt; is implemented, this model provides a clear structural difference between &lt;code&gt;forever (putStrLn &quot;Hello&quot;)&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; and does not require us to believe the pleasant fiction that we can get our hands on the real world and pass it around.&lt;/p&gt;
&lt;p&gt;Our actual &lt;code&gt;IO&lt;/code&gt; representation is only slightly more complicated than the one presented here in order to deal with the plumbing of an extra continuation to deal with Java exceptions, but the substance of this approach isn't changed by this addition.&lt;/p&gt;
&lt;p&gt;[Edit: incorporated a minor typographical fix into Iterator from Max Bolingbroke]&lt;br&gt;
[Edit: fixed Store to be data, an liftM that should have been an fmap and added the missing Functor constraint that was present in my actual implementation but didn't make it to the web, and a couple of typos in the implementation of RSIterator, all noted by Clumsy.]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Free Monads for Less (Part 2 of 3): Yoneda</title><link>https://comonad.com/reader/2011/free-monads-for-less-2/</link><guid isPermaLink="false">https://comonad.com/reader/2011/free-monads-for-less-2/</guid><pubDate>Thu, 23 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 23 June 2011&lt;/p&gt;&lt;span id=&quot;more-243&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less/&quot;&gt;Last time&lt;/a&gt;, I started exploring whether or not &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/Control-Monad-Codensity.html&quot;&gt;Codensity&lt;/a&gt; was necessary to &lt;a href=&quot;http://www.iai.uni-bonn.de/~jv/mpc08.pdf&quot;&gt;improve the asymptotic performance of free monads&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This time I'll show that the answer is no; we can get by with something smaller.&lt;/p&gt;
&lt;h2 id=&quot;the-yoneda-lemma&quot;&gt;The Yoneda Lemma&lt;/h2&gt;
&lt;p&gt;Another form of right Kan extension arises from the &lt;a href=&quot;http://en.wikipedia.org/wiki/Yoneda_lemma&quot;&gt;Yoneda lemma&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I covered it briefly in &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/&quot;&gt;my initial article on Kan extensions&lt;/a&gt;, but the inestimable Dan Piponi wrote a &lt;a href=&quot;http://blog.sigfpe.com/2006/11/yoneda-lemma.html&quot;&gt;much nicer article&lt;/a&gt; on how it implies in Haskell that given a &lt;code&gt;Functor&lt;/code&gt; instance on &lt;em&gt;f&lt;/em&gt;, this type&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; f r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is isomorphic to &lt;code&gt;f a&lt;/code&gt;, witnessed by these natural transformations:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;liftYoneda&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;liftYoneda&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; (\f -&amp;gt; fmap f a)

&lt;span class=&quot;hljs-title&quot;&gt;lowerYoneda&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;lowerYoneda&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f) = f id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That said, &lt;em&gt;you are not limited to applying &lt;code&gt;Yoneda&lt;/code&gt; to types that have &lt;code&gt;Functor&lt;/code&gt; instances&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This type and these functions are provided by &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/Data-Functor-Yoneda.html&quot;&gt;Data.Functor.Yoneda&lt;/a&gt; from the &lt;a href=&quot;https://hackage.haskell.org/package/kan-extensions&quot;&gt;kan-extensions&lt;/a&gt; package.&lt;/p&gt;
&lt;h2 id=&quot;codensity-vs-yoneda&quot;&gt;Codensity vs. Yoneda&lt;/h2&gt;
&lt;p&gt;Note, &lt;code&gt;Yoneda f&lt;/code&gt; is in some sense smaller than &lt;code&gt;Codensity f&lt;/code&gt;, as &lt;code&gt;Codensity f a&lt;/code&gt; is somewhat 'bigger' than &lt;code&gt;f a&lt;/code&gt;, despite providing an embedding, while &lt;code&gt;Yoneda f a&lt;/code&gt; is isomorphic.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;Codensity ((-&amp;gt;) s) a&lt;/code&gt; is isomorphic to &lt;code&gt;State s a&lt;/code&gt;, not to &lt;code&gt;s -&amp;gt; a&lt;/code&gt; as shown by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; ((-&amp;gt;) s)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   get = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\k s -&amp;gt; k s s)
   put s = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\k _ -&amp;gt; k () s)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;Codensity&lt;/code&gt; is a particular form of right Kan extension, which always yields a &lt;code&gt;Monad&lt;/code&gt;, &lt;strong&gt;without needing anything from &lt;em&gt;f&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here we aren't so fortunate, but we do have the fact that &lt;code&gt;Yoneda f&lt;/code&gt; is always a &lt;code&gt;Functor&lt;/code&gt;, regardless of what &lt;em&gt;f&lt;/em&gt; is, as shown by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; (\k -&amp;gt; m (k . f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which was obtained just by cutting and pasting the appropriate definition from &lt;code&gt;Codensity&lt;/code&gt; or &lt;code&gt;ContT&lt;/code&gt;, and comes about because &lt;code&gt;Yoneda&lt;/code&gt; is a right Kan extension, like all of those.&lt;/p&gt;
&lt;p&gt;To get a &lt;code&gt;Monad&lt;/code&gt; instance for &lt;code&gt;Yoneda f&lt;/code&gt; we need to lean on &lt;em&gt;f&lt;/em&gt; somehow.&lt;/p&gt;
&lt;p&gt;One way is to just borrow a &lt;code&gt;Monad&lt;/code&gt; instance from &lt;em&gt;f&lt;/em&gt;, since &lt;code&gt;f a&lt;/code&gt; is isomorphic to &lt;code&gt;Yoneda f a&lt;/code&gt;, if we have a &lt;code&gt;Functor&lt;/code&gt; for &lt;em&gt;f&lt;/em&gt;, and if we have a &lt;code&gt;Monad&lt;/code&gt;, we can definitely have a &lt;code&gt;Functor&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return a = &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; (\f -&amp;gt; return (f a))
  &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; (\f -&amp;gt; m id &amp;gt;&amp;gt;= \a -&amp;gt; runYoneda (k a) f)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;map-fusion-and-reassociating-binds&quot;&gt;Map Fusion and Reassociating Binds&lt;/h2&gt;
&lt;p&gt;Unlike &lt;code&gt;Codensity&lt;/code&gt; the monad instance above isn't very satisfying, because it uses the &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; of the underlying monad, and as a result the &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;s will wind up in the same order they started.&lt;/p&gt;
&lt;p&gt;On the other hand, the &lt;code&gt;Functor&lt;/code&gt; instance for &lt;code&gt;Yoneda f&lt;/code&gt; is still pretty nice because the &lt;code&gt;(a -&amp;gt; r)&lt;/code&gt; part of the type acts as an accumulating parameter fusing together uses of &lt;code&gt;fmap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is apparent if you expand &lt;code&gt;lowerYoneda . fmap f . fmap g . liftYoneda&lt;/code&gt; , whereupon you can see we only call &lt;code&gt;fmap&lt;/code&gt; on the underlying &lt;code&gt;Functor&lt;/code&gt; once.&lt;/p&gt;
&lt;p&gt;Intuitively, you can view &lt;code&gt;Yoneda&lt;/code&gt; as a type level construction that ensures that you get &lt;code&gt;fmap&lt;/code&gt; fusion, while &lt;code&gt;Codensity&lt;/code&gt; is a type level construction that ensures that you right associate binds. It is important to note that &lt;code&gt;Codensity&lt;/code&gt; also effectively accumulates &lt;code&gt;fmap&lt;/code&gt;s, as it uses the same definition for &lt;code&gt;fmap&lt;/code&gt; as &lt;code&gt;Yoneda&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;With this in mind, it doesn't usually make much sense to use &lt;code&gt;Codensity (Codensity m)&lt;/code&gt; or &lt;code&gt;Yoneda (Yoneda m)&lt;/code&gt; because the purpose being served is redundant.&lt;/p&gt;
&lt;p&gt;Less obviously, &lt;code&gt;Codensity (Yoneda m)&lt;/code&gt; is also redundant, because as noted above, &lt;code&gt;Codensity&lt;/code&gt; also does &lt;code&gt;fmap&lt;/code&gt; accumulation.&lt;/p&gt;
&lt;h2 id=&quot;other-yoneda-transformed-monads&quot;&gt;Other Yoneda-transformed Monads&lt;/h2&gt;
&lt;p&gt;Now, I said one way to define a &lt;code&gt;Monad&lt;/code&gt; for &lt;code&gt;Yoneda f&lt;/code&gt; was to borrow an underlying &lt;code&gt;Monad&lt;/code&gt; instance for &lt;em&gt;f&lt;/em&gt;, but this isn't the only way.&lt;/p&gt;
&lt;p&gt;Consider &lt;code&gt;Yoneda Endo&lt;/code&gt;. Recall that &lt;code&gt;Endo&lt;/code&gt; from &lt;a href=&quot;http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Data-Monoid.html&quot;&gt;Data.Monoid&lt;/a&gt; is given by&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Endo&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;appEndo&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clearly &lt;code&gt;Endo&lt;/code&gt; is not a &lt;code&gt;Monad&lt;/code&gt;, it can't even be a &lt;code&gt;Functor&lt;/code&gt;, because &lt;em&gt;a&lt;/em&gt; occurs in both positive and negative position.&lt;/p&gt;
&lt;p&gt;Nevertheless &lt;code&gt;Yoneda Endo&lt;/code&gt; &lt;strong&gt;can&lt;/strong&gt; be made into a monad -- the continuation passing style version of the &lt;code&gt;Maybe&lt;/code&gt; monad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;YMaybe&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;YMaybe&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r -&amp;gt; r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I leave the rather straightforward derivation of this &lt;code&gt;Monad&lt;/code&gt; for the reader. A version of it is present in &lt;a href=&quot;https://comonad.com/haskell/monad-ran/dist/doc/html/monad-ran/Control-Monad-Ran.html&quot;&gt;monad-ran&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This lack of care for capital-F &lt;code&gt;Functor&lt;/code&gt;iality also holds for &lt;code&gt;Codensity&lt;/code&gt;, &lt;code&gt;Codensity Endo&lt;/code&gt; can be used as a two-continuation list monad. It is isomorphic to the non-transformer version of &lt;a href=&quot;http://okmij.org/ftp/papers/LogicT.pdf&quot;&gt;Oleg et al.'s LogicT&lt;/a&gt;, which is available on hackage as &lt;a href=&quot;https://hackage.haskell.org/packages/archive/logict/0.4.2/doc/html/Control-Monad-Logic.html&quot;&gt;logict&lt;/a&gt; from my coworker, Dan Doel.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Functor&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt;, &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;MonadPlus&lt;/code&gt; and many other instances for &lt;code&gt;LogicT&lt;/code&gt; can be rederived in their full glory from &lt;code&gt;Codensity (GEndo m)&lt;/code&gt; automatically, where&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;GEndo&lt;/span&gt; m r = &lt;span class=&quot;hljs-type&quot;&gt;GEndo&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;without any need for conscious thought about how the continuations are plumbed through in the &lt;code&gt;Monad&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;bananas-in-space&quot;&gt;Bananas in Space&lt;/h2&gt;
&lt;p&gt;One last digression,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f r = (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;came up once previously on this blog in &lt;a href=&quot;https://comonad.com/reader/2008/rotten-bananas/&quot;&gt;Rotten Bananas&lt;/a&gt;. In that post, I talked about how Fegaras and Sheard used a free monad (somewhat obliquely) in &quot;&lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.2763&quot;&gt;Revisiting catamorphisms over datatypes with embedded functions&lt;/a&gt;&quot; to extend catamorphisms to deal with strong HOAS, and then talked further about how Stephanie Weirich and Geoffrey Washburn &lt;a href=&quot;http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.80.2219&quot;&gt;used Rec&lt;/a&gt; to replace the free monad used by Fegaras and Sheard. That said, they did so in a more restricted context, where any mapping was done by giving us both an embedding and a projection pair.&lt;/p&gt;
&lt;h2 id=&quot;going-to-church&quot;&gt;Going to Church&lt;/h2&gt;
&lt;p&gt;We can't just use &lt;code&gt;Rec f a&lt;/code&gt; instead of &lt;code&gt;Free f a&lt;/code&gt; here, because &lt;code&gt;Free f a&lt;/code&gt; is a functor, while &lt;code&gt;Rec f a&lt;/code&gt; is emphatically not.&lt;/p&gt;
&lt;p&gt;However, if we apply &lt;code&gt;Yoneda&lt;/code&gt; to &lt;code&gt;Rec f&lt;/code&gt;, we obtain a Church-encoded continuation-passing-style version of &lt;code&gt;Free&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runF&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since this is of the form of &lt;code&gt;Yoneda (Rec f)&lt;/code&gt;, it is clearly a &lt;code&gt;Functor&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   fmap f (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; g) = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp -&amp;gt; g (kp . f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And nicely, &lt;strong&gt;without knowing anything about &lt;em&gt;f&lt;/em&gt;&lt;/strong&gt;, we also get a &lt;code&gt;Monad&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return a = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp _ -&amp;gt; kp a)
   &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp kf -&amp;gt; m (\a -&amp;gt; runF (f a) kp kf) kf)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But when we &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; all we do is change the continuation for &lt;code&gt;(a -&amp;gt; r)&lt;/code&gt;, leaving the &lt;em&gt;f&lt;/em&gt;-algebra, &lt;code&gt;(f r -&amp;gt; r)&lt;/code&gt;, untouched.&lt;/p&gt;
&lt;p&gt;Now, &lt;code&gt;F&lt;/code&gt; is a monad transformer:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   lift f = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp kf -&amp;gt; kf (liftM kp f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is unsurprisingly, effectively performing the same operation as lifting did in &lt;code&gt;Free&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Heretofore, we've ignored everything about &lt;em&gt;f&lt;/em&gt; entirely.&lt;/p&gt;
&lt;p&gt;This has pushed the need for the &lt;code&gt;Functor&lt;/code&gt; on &lt;em&gt;f&lt;/em&gt; into the wrapping operation:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   wrap f = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp kf -&amp;gt; kf (fmap (\ (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; m) -&amp;gt; m kp kf) f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can clearly transform from our representation to any other free monad representation:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fromF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;fromF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; m) = m return wrap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or to it from our original canonical ADT-based free monad representation:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;toF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;toF&lt;/span&gt; xs = &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (\kp kf -&amp;gt; go kp kf xs) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  go kp _  (&lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a) = kp a
  go kp kf (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; fma) = kf (fmap (go kp kf) fma)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, &lt;code&gt;F f a&lt;/code&gt; is isomorphic to &lt;code&gt;Free f a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, looking at &lt;code&gt;Codensity (F f) a&lt;/code&gt; as &lt;code&gt;Codensity (Yoneda (Rec f))&lt;/code&gt;, it just seems silly.&lt;/p&gt;
&lt;p&gt;As we mentioned before, we should be able to go from &lt;code&gt;Codensity (Yoneda (Rec f)) a&lt;/code&gt; to &lt;code&gt;Codensity (Rec f) a&lt;/code&gt;, since &lt;code&gt;Yoneda&lt;/code&gt; was just fusing uses of &lt;code&gt;fmap&lt;/code&gt;, while &lt;code&gt;Codensity&lt;/code&gt; was fusing &lt;code&gt;fmap&lt;/code&gt; while right-associating &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt;'s.&lt;/p&gt;
&lt;h2 id=&quot;swallowing-the-bigger-fish&quot;&gt;Swallowing the Bigger Fish&lt;/h2&gt;
&lt;p&gt;So, the obvious choice is to try to optimize to &lt;code&gt;Codensity (Rec f) a&lt;/code&gt;. If you go through the motions of encoding that you get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;CF&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;CF&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r) -&amp;gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is in some sense larger than &lt;code&gt;F f a&lt;/code&gt;, because the first continuation gets both an &lt;em&gt;a&lt;/em&gt; and an &lt;em&gt;f&lt;/em&gt;-algebra &lt;code&gt;(f r -&amp;gt; r)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But tellingly, once you write the code, the first continuation &lt;strong&gt;never uses the extra &lt;em&gt;f&lt;/em&gt;-algebra you supplied it!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;Codensity (Yoneda (Rec f)) a&lt;/code&gt; gives us nothing of interest that we don't already have in &lt;code&gt;Yoneda (Rec f) a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Consequently, in this special case rather than letting &lt;code&gt;Codensity (Yoneda x) a&lt;/code&gt; swallow the &lt;code&gt;Yoneda&lt;/code&gt; to get &lt;code&gt;Codensity x a&lt;/code&gt; we can actually let the &lt;code&gt;Yoneda&lt;/code&gt; swallow the surrounding &lt;code&gt;Codensity&lt;/code&gt; obtaining &lt;code&gt;Yoneda (Rec f) a&lt;/code&gt;, the representation we started with.&lt;/p&gt;
&lt;h2 id=&quot;scott-free&quot;&gt;Scott Free&lt;/h2&gt;
&lt;p&gt;Finally, you might ask if a Church encoding is as simple as we could go. After all a Scott encoding&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt;&lt;/span&gt;
    { runScottFree :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; r.
       (a -&amp;gt; r) -&amp;gt; (f (&lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt; f a) -&amp;gt; r) -&amp;gt; r
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;would admit easier pattern matching, and a nice pun, and seems somewhat conceptually simpler, while remaining isomorphic.&lt;/p&gt;
&lt;p&gt;But the &lt;code&gt;Monad&lt;/code&gt; instance:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return a = &lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt; (\kp _ -&amp;gt; kp a)
   &lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt; m &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;ScottFree&lt;/span&gt;
       (\kb kf -&amp;gt; m (\a -&amp;gt; runScottFree (f a) kb kf) (kf . fmap (&amp;gt;&amp;gt;= f)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;needs to rely on the underlying bind, and you can show that it won't do the right thing with regards to reassociating.&lt;/p&gt;
&lt;p&gt;So, alas, we cannot get away with &lt;code&gt;ScottFree&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;nobody-sells-for-less&quot;&gt;Nobody Sells for Less&lt;/h2&gt;
&lt;p&gt;So, now we can rebuild Voigtländer's &lt;code&gt;improve&lt;/code&gt; using our Church-encoded / Yoneda-based free monad &lt;code&gt;F&lt;/code&gt;, which is precisely isomorphic to &lt;code&gt;Free&lt;/code&gt;, by using&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lowerF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;lowerF&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; f) = f &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to obtain&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;improve&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f m =&amp;gt; m a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;improve&lt;/span&gt; m = lowerF m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And since our Church-encoded free monad is isomorphic to the simple ADT encoding, our new solution is as small as it can get.&lt;/p&gt;
&lt;p&gt;Next time, we'll see this construction in action!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Free Monads for Less (Part 1 of 3): Codensity</title><link>https://comonad.com/reader/2011/free-monads-for-less/</link><guid isPermaLink="false">https://comonad.com/reader/2011/free-monads-for-less/</guid><pubDate>Thu, 23 Jun 2011 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 23 June 2011&lt;/p&gt;&lt;span id=&quot;more-218&quot;&gt;&lt;/span&gt;&lt;p&gt;A couple of years back &lt;a href=&quot;http://www.iai.uni-bonn.de/~jv/&quot;&gt;Janis Voigtländer&lt;/a&gt; wrote &lt;a href=&quot;http://www.iai.uni-bonn.de/~jv/mpc08.pdf&quot;&gt;a nice paper&lt;/a&gt; on how one can use the codensity monad to improve the asymptotic complexity of algorithms using the free monads. He didn't use the name &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/Control-Monad-Codensity.html&quot;&gt;Codensity&lt;/a&gt; in the paper, but this is essentially the meaning of his type &lt;code&gt;C&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I just returned from &lt;a href=&quot;http://www.cas.mcmaster.ca/~anand/DSL2011.html&quot;&gt;running a workshop on domain-specific languages at McMaster University&lt;/a&gt; with the more than able assistance of &lt;a href=&quot;http://llama.freegeek.org/~wren/thornton_cv.pdf&quot;&gt;Wren Ng Thornton&lt;/a&gt;. Among the many topics covered, I spent a lot of time talking about how to use free monads to build up term languages for various DSLs with simple evaluators, and then made them efficient by using &lt;code&gt;Codensity&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This has been shown to be a sufficient tool for this task, but is it necessary?&lt;/p&gt;
&lt;p&gt;First, some context:&lt;/p&gt;
&lt;h2 id=&quot;monads-for-free&quot;&gt;Monads for Free&lt;/h2&gt;
&lt;p&gt;Given that &lt;em&gt;f&lt;/em&gt; is a &lt;code&gt;Functor&lt;/code&gt;, we get that&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is a &lt;code&gt;Monad&lt;/code&gt; for free:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; (f a)
   fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (fmap (fmap f) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   return = &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a &lt;span class=&quot;hljs-comment&quot;&gt;-- the first monad law!&lt;/span&gt;
   &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &amp;gt;&amp;gt;= f = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (fmap (&amp;gt;&amp;gt;= f) &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition is also free in a particular categorical sense, that if &lt;em&gt;f&lt;/em&gt; is a monad, then, and you have a forgetful functor that forgets that it is a monad and just yields the functor, then the the free construction above is left adjoint to it.&lt;/p&gt;
&lt;p&gt;This type and much of the code below is actually provided by &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonad-transformers/1.7/doc/html/Control-Monad-Trans-Free.html&quot;&gt;Control.Monad.Trans.Free&lt;/a&gt; in the &lt;a href=&quot;https://hackage.haskell.org/package/comonad-transformers&quot;&gt;comonad-transformers&lt;/a&gt; package on hackage.&lt;/p&gt;
&lt;p&gt;For a while, Free lived in a separate, now defunct, package named &lt;code&gt;free&lt;/code&gt; with its dual &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonad-transformers/1.7/doc/html/Control-Comonad-Trans-Cofree.html&quot;&gt;Cofree&lt;/a&gt;, but it was merged into comonad-transformers due to complications involving &lt;a href=&quot;https://hackage.haskell.org/package/comonads-fd&quot;&gt;comonads-fd&lt;/a&gt;, the comonadic equivalent of the mtl. Arguably, a better home would be transformers, to keep symmetry.&lt;/p&gt;
&lt;h2 id=&quot;free-is-a-monad-transformer&quot;&gt;Free is a Monad Transformer&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    lift = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; . liftM &lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and there exists a &lt;a href=&quot;http://en.wikipedia.org/wiki/Retract_(category_theory)&quot;&gt;retraction&lt;/a&gt; for lift&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;retract&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;retract&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Pure&lt;/span&gt; a) = return a
&lt;span class=&quot;hljs-title&quot;&gt;retract&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &amp;gt;&amp;gt;= retract
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;such that &lt;code&gt;retract . lift = id&lt;/code&gt;. I've &lt;a href=&quot;http://stackoverflow.com/questions/6221531/how-to-convert-a-free-monad-into-a-functor/6231795#6231795&quot;&gt;spoken about this on Stack Overflow&lt;/a&gt;, including the rather trivial proof, previously.&lt;/p&gt;
&lt;p&gt;This lets us work in &lt;code&gt;Free m a&lt;/code&gt;, then flatten back down to a single layer of &lt;em&gt;m&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This digression will be useful in a subsequent post.&lt;/p&gt;
&lt;h2 id=&quot;monadfree&quot;&gt;MonadFree&lt;/h2&gt;
&lt;p&gt;What Janis encapsulated in his paper is the notion that we can abstract out the extra power granted by a free monad to add layers of &lt;em&gt;f&lt;/em&gt; to some monad &lt;em&gt;m&lt;/em&gt;, and then use a better representation to improve the asymptotic performance of the monad.&lt;/p&gt;
&lt;p&gt;The names below have been changed slightly from his presentation.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f m | m -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    wrap :: f (m a) -&amp;gt; m a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    wrap = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;instances can easily be supplied to lift &lt;code&gt;MonadFree&lt;/code&gt; over the common monad transformers. For instance:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;ReaderT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    wrap fs = &lt;span class=&quot;hljs-type&quot;&gt;ReaderT&lt;/span&gt; $ \e -&amp;gt; wrap $ fmap (`runReaderT` e) fs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This functionality is provided by &lt;a href=&quot;https://hackage.haskell.org/packages/archive/comonads-fd/1.7/doc/html/Control-Monad-Free-Class.html&quot;&gt;Control.Monad.Free.Class&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Janis then proceeded to define the aforementioned type &lt;code&gt;C&lt;/code&gt;, which is effectively identical to&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; f r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This type is supplied by &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/Control-Monad-Codensity.html&quot;&gt;Control.Monad.Codensity&lt;/a&gt; from my &lt;a href=&quot;https://hackage.haskell.org/package/kan-extensions&quot;&gt;kan-extensions&lt;/a&gt; package on hackage.&lt;/p&gt;
&lt;p&gt;I have spoken about this type (and another that will arise in a subsequent post) on this blog previously, in a series of posts on Kan Extensions. [ &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://comonad.com/reader/2008/kan-extension-iii/&quot;&gt;3&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Codensity f&lt;/code&gt; is a &lt;code&gt;Monad&lt;/code&gt;, &lt;strong&gt;regardless&lt;/strong&gt; of what &lt;em&gt;f&lt;/em&gt; is!&lt;/p&gt;
&lt;p&gt;In fact, you can quite literally cut and paste much of the definitions for &lt;code&gt;return&lt;/code&gt;, &lt;code&gt;fmap&lt;/code&gt;, and &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; from the code for the &lt;code&gt;ContT&lt;/code&gt; monad transformer! Compare&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; m) = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\k -&amp;gt; m (k . f))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return x = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\k -&amp;gt; k x)
  m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\c -&amp;gt; runCodensity m (\a -&amp;gt; runCodensity (k a) c))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   lift m = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (m &amp;gt;&amp;gt;=)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;from &lt;a href=&quot;https://hackage.haskell.org/packages/archive/kan-extensions/0.5.0/doc/html/src/Control-Monad-Codensity.html&quot;&gt;Control.Monad.Codensity&lt;/a&gt; in &lt;a href=&quot;https://hackage.haskell.org/package/kan-extensions&quot;&gt;kan-extensions&lt;/a&gt; with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f m = &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; $ \c -&amp;gt; runContT m (c . f)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    return a = &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; ($ a)
    m &amp;gt;&amp;gt;= k  = &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; $ \c -&amp;gt; runContT m (\a -&amp;gt; runContT (k a) c)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadTrans&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    lift m = &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; (m &amp;gt;&amp;gt;=)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;from the &lt;a href=&quot;https://hackage.haskell.org/packages/archive/transformers/0.2.2.0/doc/html/src/Control-Monad-Trans-Cont.html&quot;&gt;Control.Monad.Trans.Cont&lt;/a&gt; in &lt;a href=&quot;https://hackage.haskell.org/package/transformers-0.2.2.0&quot;&gt;transformers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Codensity m a&lt;/code&gt; is effectively &lt;code&gt;forall r. ContT r m a&lt;/code&gt;. This turns out to be just enough of a restriction to rule out the use of &lt;a href=&quot;https://hackage.haskell.org/packages/archive/transformers/0.2.2.0/doc/html/Control-Monad-Trans-Cont.html#v:callCC&quot;&gt;callCC&lt;/a&gt;, while leaving the very powerful fact that when you lower them back down using&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lowerCodensity&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; m a -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;lowerCodensity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; m) = m return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runContT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; r m a -&amp;gt; m r
&lt;span class=&quot;hljs-title&quot;&gt;runContT&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; m) = m return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ContT&lt;/code&gt; and &lt;code&gt;Codensity&lt;/code&gt; both yield a result in which all of the uses of the underlying monad's &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt; are right associated.&lt;/p&gt;
&lt;p&gt;This can be convenient for two reasons:&lt;/p&gt;
&lt;p&gt;First, some almost-monads are not associative, and converting to ContT or Codensity can be used to fix this fact.&lt;/p&gt;
&lt;p&gt;Second, in many monads, when you build a big structure using left associated binds, like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;    (f &amp;gt;&amp;gt;= g) &amp;gt;&amp;gt;= h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rather than use right associated binds like&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;   f &amp;gt;&amp;gt;= \x -&amp;gt; g x &amp;gt;&amp;gt;= h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then you wind up building a structure, then tearing it down and building up a whole new structure. This can compromise the productivity of the result, and it can also affect the asymptotic performance of your code.&lt;/p&gt;
&lt;p&gt;Even though the monad laws say these two yield the same answer.&lt;/p&gt;
&lt;h2 id=&quot;the-dual-of-substitution-is-redecoration&quot;&gt;The dual of substitution is redecoration&lt;/h2&gt;
&lt;p&gt;To see that, first, it is worth noting that about ten years back, Tarmo Uustalu and Varmo Vene wrote &quot;&lt;a href=&quot;http://www.ioc.ee/~tarmo/papers/sfp01-book.pdf&quot;&gt;The dual of substitition is redecoration&lt;/a&gt;&quot;, which among other things quite eloquently described how monads are effectively about substituting new tree-like structures, and then renormalizing.&lt;/p&gt;
&lt;p&gt;This can be seen in terms of the more categorical viewpoint, where we define a monad in terms of &lt;code&gt;return&lt;/code&gt;, &lt;code&gt;fmap&lt;/code&gt; and &lt;code&gt;join&lt;/code&gt;, rather than &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt;. In that presentation:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;gt;&amp;gt;= f = join (fmap f m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;fmap&lt;/code&gt; is performing substitution. and &lt;code&gt;join&lt;/code&gt; is dealing with any renormalization.&lt;/p&gt;
&lt;p&gt;Done this way, &lt;code&gt;(m &amp;gt;&amp;gt;= f)&lt;/code&gt; on the &lt;code&gt;Maybe&lt;/code&gt; monad would first &lt;code&gt;fmap&lt;/code&gt; to obtain &lt;code&gt;Just (Just a)&lt;/code&gt;, &lt;code&gt;Just Nothing&lt;/code&gt; or &lt;code&gt;Nothing&lt;/code&gt; before flattening.&lt;/p&gt;
&lt;p&gt;In the Maybe a case, the association of your binds is largely immaterial, the normalization pass fixes things up to basically the same size, but in the special case of a free monad the monad is &lt;strong&gt;purely defined in terms of substitution&lt;/strong&gt;, since:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- join :: Functor f =&amp;gt; Free f (Free f a) -&amp;gt; Free f a&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- join (Pure a) = a&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- join (Free as) = Free (fmap join as)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that every time you &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; a free monad you are accumulating structure -- structure that you have traverse past to deal with subsequent left-associated invocations of &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;! Free monads never shrink after a bind and the main body of the tree never changes.&lt;/p&gt;
&lt;p&gt;More concretely, you could build a binary tree with&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- data Tree a = Tip a | Bin (Tree a) (Tree a)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and make a monad out of it, writing out your &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;(&amp;gt;&amp;gt;=)&lt;/code&gt;, etc. by hand&lt;/p&gt;
&lt;p&gt;The same monad could be had 'for free' by taking the free monad of&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a a&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Foldable&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt;)
    &lt;span class=&quot;hljs-comment&quot;&gt;-- using LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yielding the admittedly slightly less convenient type signature&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can use &lt;code&gt;return&lt;/code&gt; for &lt;code&gt;Tip&lt;/code&gt;, and&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; m =&amp;gt; m a -&amp;gt; m a -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; l r = wrap (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; l r)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to construct a binary tree node, using any free monad representation.&lt;/p&gt;
&lt;p&gt;Now, if that representation is &lt;code&gt;Free Bin&lt;/code&gt; (or the original more direct &lt;code&gt;Tree&lt;/code&gt; type above) then code that looks like &lt;code&gt;f &amp;gt;&amp;gt;= \x -&amp;gt; g x &amp;gt;&amp;gt;= h&lt;/code&gt; performs fine, but &lt;code&gt;(f &amp;gt;&amp;gt;= g) &amp;gt;&amp;gt;= h&lt;/code&gt; will retraverse the unchanging 'trunk' of the tree structure twice. That isn't so bad, but given n uses of &amp;gt;&amp;gt;= we'll traverse an ever-growing trunk over and over &lt;em&gt;n&lt;/em&gt; times!&lt;/p&gt;
&lt;h2 id=&quot;putting-codensity-to-work&quot;&gt;Putting Codensity to Work&lt;/h2&gt;
&lt;p&gt;But, we have a tool that can fix this, &lt;code&gt;Codensity&lt;/code&gt;!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  wrap t = &lt;span class=&quot;hljs-type&quot;&gt;Codensity&lt;/span&gt; (\h -&amp;gt; wrap (fmap (\p -&amp;gt; runCodensity p h) t))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Janis packaged up the use of &lt;code&gt;Codensity&lt;/code&gt; into a nice combinator that you can sprinkle through your code, so that your users never need know it exists. Moreover, it prevents them from accidentally using any of the extra power of the intermediate representation. If your code typechecks before you use improve somewhere within it, and it type checks after, then it will yield the same answer.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;improve&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; m. &lt;span class=&quot;hljs-type&quot;&gt;MonadFree&lt;/span&gt; f m =&amp;gt; m a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;improve&lt;/span&gt; m = lowerCodensity m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By now, it should be clear that the power of &lt;code&gt;Codensity&lt;/code&gt; is sufficient to the task, but is it necessary?&lt;/p&gt;
&lt;p&gt;More Soon.&lt;/p&gt;
&lt;p&gt;[Edit; Fixed minor typographical errors pointed out by ShinNoNoir, ivanm, and Josef Svenningsson, including a whole bunch of them found by Noah Easterly]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2011/free-monads-for-less/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Lenses: A Functional Imperative</title><link>https://comonad.com/reader/talks/kmett-2011-lenses-functional-imperative/</link><guid isPermaLink="false">https://comonad.com/reader/talks/kmett-2011-lenses-functional-imperative/</guid><pubDate>Tue, 24 May 2011 12:00:00 GMT</pubDate><category>Talk</category><description>&lt;p&gt;Edward Kmett · 24 May 2011&lt;/p&gt;&lt;figure class=&quot;talk-video&quot; data-video-id=&quot;efv0SQNde5Q&quot;&gt;&lt;figcaption&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=efv0SQNde5Q&quot;&gt;Watch on YouTube&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Lenses: A Functional Imperative — Boston Area Scala Enthusiasts (BASE), Google Cambridge.&lt;/p&gt;
&lt;h2&gt;Materials&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=efv0SQNde5Q&quot;&gt;Lenses: A Functional Imperative [1/5]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XVmhK8WbRLY&quot;&gt;Lenses: A Functional Imperative [2/5]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=QjatJWIJBTM&quot;&gt;Lenses: A Functional Imperative [3/5]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=CXH1V4xS2W0&quot;&gt;Lenses: A Functional Imperative [4/5]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YiFcvqRM6AA&quot;&gt;Lenses: A Functional Imperative [5/5]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/talks/kmett-2011-lenses-functional-imperative/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Introducing Speculation</title><link>https://comonad.com/reader/2010/introducing-speculation/</link><guid isPermaLink="false">https://comonad.com/reader/2010/introducing-speculation/</guid><pubDate>Thu, 22 Jul 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 22 July 2010&lt;/p&gt;&lt;span id=&quot;more-205&quot;&gt;&lt;/span&gt;&lt;p&gt;A couple of days ago, I gave a talk at Boston Haskell about a shiny new speculative evaluation library, &lt;a href=&quot;https://hackage.haskell.org/package/speculation&quot;&gt;speculation&lt;/a&gt; on hackage, that I have implemented in Haskell. The implementation is based on the material presented as &lt;a href=&quot;http://research.microsoft.com/apps/pubs/default.aspx?id=118795&quot;&gt;&quot;Safe Programmable Speculative Parallelism&quot;&lt;/a&gt; by Prakash Prabhu, G Ramalingam, and Kapil Vaswani at last month's PLDI.&lt;/p&gt;
&lt;p&gt;I've uploaded a copy of my slides here:&lt;/p&gt;
&lt;p&gt;* Introducing Speculation [&lt;a href=&quot;https://comonad.com/assets/imported/c7458306600d-Speculation.pptx&quot;&gt;PowerPoint&lt;/a&gt; | &lt;a href=&quot;https://comonad.com/assets/imported/9322df7a9bb3-Speculation.pdf&quot;&gt;PDF&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;This package provides speculative function application and speculative folds. Speculative STM transactions take the place of the transactional rollback machinery from the paper, but transactions are not always required in pure code. To get a feel for the shape of the library, here is an excerpt from the &lt;a href=&quot;https://hackage.haskell.org/package/speculation&quot;&gt;documentation&lt;/a&gt; for one of the combinators:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;spec&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; a -&amp;gt; (a -&amp;gt; b) -&amp;gt; a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;spec g f a&lt;/code&gt; evaluates &lt;code&gt;f g&lt;/code&gt; while forcing &lt;code&gt;a&lt;/code&gt;, if &lt;code&gt;g == a&lt;/code&gt; then &lt;code&gt;f g&lt;/code&gt; is returned, otherwise &lt;code&gt;f a&lt;/code&gt; is evaluated and returned. Furthermore, if the argument has already been evaluated, we skip the &lt;code&gt;f g&lt;/code&gt; computation entirely. If a good guess at the value of &lt;code&gt;a&lt;/code&gt; is available, this is one way to induce parallelism in an otherwise sequential task. However, if the guess isn't available more cheaply than the actual answer, then this saves no work and if the guess is wrong, you risk evaluating the function twice. Under high load, since &lt;code&gt;f g&lt;/code&gt; is computed via the spark queue, the speculation will be skipped and you will obtain the same answer as &lt;code&gt;f $! a&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ASCII art time-lines of how this can speed up evaluation are available in both the slides and the documentation linked to above, but assuming an otherwise serial problem, you effectively wager otherwise idle CPU time and the time to generate your guess on the quality of your guess.&lt;/p&gt;
&lt;p&gt;Note that &lt;a href=&quot;https://hackage.haskell.org/trac/ghc/ticket/4167&quot;&gt;numSparks# feature request&lt;/a&gt; that was mentioned in the slides has already been implemented in GHC HEAD, and support shall be added to improve the performance of the speculative STM transactions under high load as mentioned in the slides.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/introducing-speculation/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Boston Haskell June</title><link>https://comonad.com/reader/2010/boston-haskell-june/</link><guid isPermaLink="false">https://comonad.com/reader/2010/boston-haskell-june/</guid><pubDate>Thu, 20 May 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 20 May 2010&lt;/p&gt;&lt;span id=&quot;more-202&quot;&gt;&lt;/span&gt;&lt;p&gt;I've put together a poll about when folks would like to have the next meeting, if you're going to be in the area, please help us pick a date and time that works for you!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.doodle.com/ux8mqaa9h2tngf6k&quot;&gt;http://www.doodle.com/ux8mqaa9h2tngf6k&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I pushed the dates out a little ways so we wouldn't be overlapping with Hac-Phi.&lt;/p&gt;
&lt;p&gt;A couple of folks indicated that they had material they'd like to present this next time. If you want to present this month (or in the near future), please email me. Otherwise I'll have no choice but to blather on about category theory or automatic differentiation and there won't be a newbie left within earshot inside of 10 minutes.&lt;/p&gt;
&lt;p&gt;Once we get a feel for the day people prefer, and what works for the presenters I'll follow up with the date, venue and summary of what is being presented, but for this session we'll likely set up in the CSAIL reading room again and I'll try to co-opt Chris into baking more cookies.&lt;/p&gt;
&lt;p&gt;Please feel free to email me with any questions or concerns!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/boston-haskell-june/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Hac Phi</title><link>https://comonad.com/reader/2010/hac-phi/</link><guid isPermaLink="false">https://comonad.com/reader/2010/hac-phi/</guid><pubDate>Thu, 20 May 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 20 May 2010&lt;/p&gt;&lt;p&gt;I'm going to be out at &lt;a href=&quot;http://haskell.org/haskellwiki/Hac_%CF%86&quot;&gt;Hac φ&lt;/a&gt; over the weekend cobbling together random bits and pieces of code, if you're going to be in the Philadelphia area, look us up!&lt;/p&gt;
&lt;p&gt;In particular, I plan to spend my time working on my automatic differentiation library adding different directional traversals, and trying to combine them into a coherent framework.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/hac-phi/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Brodal-Okasaki Heaps in Haskell</title><link>https://comonad.com/reader/2010/brodal-okasaki-heaps-in-haskell/</link><guid isPermaLink="false">https://comonad.com/reader/2010/brodal-okasaki-heaps-in-haskell/</guid><pubDate>Sat, 15 May 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 May 2010&lt;/p&gt;&lt;span id=&quot;more-187&quot;&gt;&lt;/span&gt;&lt;p&gt;I've uploaded a package named &lt;a href=&quot;https://hackage.haskell.org/packages/archive/heaps/0.2/doc/html/Data-Heap.html&quot;&gt;heaps&lt;/a&gt; to Hackage that provides &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973&quot;&gt;Brodal-Okasaki bootstrapped skew-binomial heaps&lt;/a&gt; in Haskell.&lt;/p&gt;
&lt;p&gt;The main features of the library are that it provides a nice &lt;a href=&quot;https://hackage.haskell.org/package/containers&quot;&gt;containers&lt;/a&gt;-like API with provably asymptotically optimal functional heap operations including O(1) insert and O(1) union, and that the library design jump through a number of hoops to provide implementations of common Haskell typeclasses such as &lt;a href=&quot;http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base/Data-Foldable.html&quot;&gt;Foldable&lt;/a&gt;, Data and Typeable.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/brodal-okasaki-heaps-in-haskell/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Reverse-Mode Automatic Differentiation in Haskell</title><link>https://comonad.com/reader/2010/reverse-mode-automatic-differentiation-in-haskell/</link><guid isPermaLink="false">https://comonad.com/reader/2010/reverse-mode-automatic-differentiation-in-haskell/</guid><pubDate>Sat, 15 May 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 May 2010&lt;/p&gt;&lt;span id=&quot;more-183&quot;&gt;&lt;/span&gt;&lt;p&gt;I've uploaded a package named &lt;a href=&quot;https://hackage.haskell.org/package/rad&quot;&gt;rad&lt;/a&gt; to Hackage for handling reverse-mode &lt;a href=&quot;http://en.wikipedia.org/wiki/Automatic_differentiation&quot;&gt;automatic differentiation&lt;/a&gt; in Haskell.&lt;/p&gt;
&lt;p&gt;Internally, it leverages a &lt;a href=&quot;http://www.ittc.ku.edu/~andygill/papers/reifyGraph.pdf&quot;&gt;trick&lt;/a&gt; from Andy Gill's Kansas Lava to observe sharing in the tape it records for back propagation purposes, and uses type level branding to avoid confusing sensitivities.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/reverse-mode-automatic-differentiation-in-haskell/#ad-figure&quot;&gt;Try the interactive example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've tried to keep the API relatively close to that of Barak Pearlmutter and Jeffrey Mark Siskind's &lt;a href=&quot;https://hackage.haskell.org/package/fad&quot;&gt;fad&lt;/a&gt; package, but I couldn't resist making a couple of minor tweaks here and there for generality.&lt;/p&gt;
&lt;p&gt;I still need to go through and finish up the remaining unimplemented fad combinators, figure out a nice way to build a reverse-mode AD tower, validate that I didn't screw up my recollection of basic calculus, and provide a nice API for using this approach to get local reverse mode checkpoints in an otherwise forward mode AD program, but I am quite happy with how things have progressed thus far.&lt;/p&gt;
&lt;p&gt;[Edit: I've uploaded minor bug fixes for exp and (**)]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/reverse-mode-automatic-differentiation-in-haskell/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Finger Trees</title><link>https://comonad.com/reader/2010/finger-trees/</link><guid isPermaLink="false">https://comonad.com/reader/2010/finger-trees/</guid><pubDate>Thu, 29 Apr 2010 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 29 April 2010&lt;/p&gt;&lt;span id=&quot;more-174&quot;&gt;&lt;/span&gt;&lt;p&gt;I gave a talk last night at &lt;a href=&quot;http://www.haskell.org/haskellwiki/Boston_Area_Haskell_Users%27_Group&quot;&gt;Boston Haskell&lt;/a&gt; on finger trees.&lt;/p&gt;
&lt;p&gt;In particular I spent a lot of time focusing on how to derive the construction of Hinze and Paterson's 2-3 finger trees via an extended detour into a whole menagerie of tree types, and less on particular applications of the final resulting structure.&lt;/p&gt;
&lt;p&gt;Overall, I think the talk went over quite well.&lt;/p&gt;
&lt;p&gt;In other finger-tree-related news, Mark Chu-Carroll recently wrote a &lt;a href=&quot;http://scienceblogs.com/goodmath/2010/04/finger_trees_done_right_i_hope.php&quot;&gt;blog post on finger trees&lt;/a&gt; as well, which might serve as a faster introduction in case you don't want to wade through 50 slides before seeing something recognizable as a finger tree. The comments given in reply to his very timely article were very useful in fleshing out this presentation.&lt;/p&gt;
&lt;p&gt;For those who are interested, while we have yet to establish a good way to record video, here are my slides.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/imported/64f0f408248f-Finger-Trees.pdf&quot;&gt;Finger Trees [PDF]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are two parts of the talk that may be difficult to adequately reconstruct from the slides alone:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I talked through the notion of safe and dangerous digits in a Hinze and Paterson tree and explained how the extra slop in a Hinze and Paterson tree work.&lt;/li&gt;
&lt;li&gt;The other part that was talked through largely via the blackboard was how one uses the monotonicity of the function passed to split.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Otherwise, you can probably reconstruct the narrative from the slides.&lt;/p&gt;
&lt;p&gt;If you have any questions or spot any errors or grievous omissions, please feel free to contact me.&lt;/p&gt;
&lt;p&gt;[Edit: Updated slide 54]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2010/finger-trees/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Iteratees, Parsec, and Monoids, Oh My!</title><link>https://comonad.com/reader/2009/iteratees-take-2/</link><guid isPermaLink="false">https://comonad.com/reader/2009/iteratees-take-2/</guid><pubDate>Tue, 15 Sep 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 September 2009&lt;/p&gt;&lt;p&gt;I'll be giving a talk tomorrow, Wednesday, September 16th, 2009 at the &lt;a href=&quot;http://www.haskell.org/haskellwiki/Boston_Area_Haskell_Users'_Group&quot;&gt;Boston Haskell User Group&lt;/a&gt; in the MIT CSAIL Reading Room (on the 8th floor of the William H. Gates tower of the Stata center) about mixing Oleg's iteratees with parsec and monoids to build practical parallel parsers and to cheaply reparse after local modifications are made to source code.&lt;/p&gt;
&lt;p&gt;Ravi is trying to organize some time before hand during which people can get together and work on Haskell projects, or spend some time learning Haskell, so its not all scary academic stuff.&lt;/p&gt;
&lt;p&gt;The meeting is scheduled from 7-9pm, and an ever growing number of us have been wandering down to the Cambridge Brewing Company afterwards to hang out and talk.&lt;/p&gt;
&lt;p&gt;If you are curious about Haskell, or even an expert, or just happen to be interested in parallel programming and find yourself in the area, come on by.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/iteratees-take-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Remodeling Precision</title><link>https://comonad.com/reader/2009/remodeling-precision/</link><guid isPermaLink="false">https://comonad.com/reader/2009/remodeling-precision/</guid><pubDate>Tue, 15 Sep 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 September 2009&lt;/p&gt;&lt;span id=&quot;more-151&quot;&gt;&lt;/span&gt;&lt;p&gt;Two concepts come up when talking about information retrieval in most standard documentation, &lt;a href=&quot;http://en.wikipedia.org/wiki/Precision_and_recall&quot;&gt;Precision and Recall&lt;/a&gt;. Precision is a measure that tells you if your result set contains only results that are relevant to the query, and recall tells you if your result set contains everything that is relevant to the query.&lt;/p&gt;
&lt;p&gt;The formula for classical precision is:&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/assets/imported/f3ffccec8735-precision_formula.png&quot; alt=&quot;Precision Formula&quot; title=&quot;Precision Formula&quot;&gt;&lt;/p&gt;
&lt;p&gt;However, I would argue that the classical notion of Precision is flawed, in that it doesn't model anything we tend to care about. Rarely are we interested in binary classification, instead we want a ranked classification of relevance.&lt;/p&gt;
&lt;p&gt;When Google tells you that you have a million results, do you care? No, you skim the first few entries for what it is that you are looking for, unless you are particularly desperate for an answer. So really, you want a metric that models the actual behavior of a search engine user and that level of desperation.&lt;/p&gt;
&lt;p&gt;There are two issues with classical precision:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the denominator of precision goes to infinity as the result set increases in size&lt;/li&gt;
&lt;li&gt;each result is worth the same amount no matter where it appears in the list&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The former ensures that a million answers drowns out any value from the first screen, the latter ensures that it doesn't matter which results are on the first screen. A more accurate notion of precision suitable for modern search interfaces should model the prioritization of the results, and should allow for a long tail of crap if the stuff that people will look at is accurate over all.&lt;/p&gt;
&lt;p&gt;So how to model user behavior? We can replace the denominator with a partial sum of a geometric series for probability &lt;em&gt;p&lt;/em&gt; &amp;lt; 1, where &lt;em&gt;p&lt;/em&gt; models the percentage chance that a user will continue to browse to the next item in the list. Then you can scale the value of the nth summand in the numerator as being worth up to &lt;em&gt;p&lt;/em&gt;&lt;sup&gt;&lt;em&gt;n&lt;/em&gt;&lt;/sup&gt;. If you have a ranked training set it is pretty easy to score precision in this fashion.&lt;/p&gt;
&lt;p&gt;You retain all of the desirable properties of precision. It maxes out at 100%, it decreases when you give irrelevant results, but now it effectively models when you return irrelevant results early in your result list.&lt;/p&gt;
&lt;p&gt;The result more accurately models user behavior when faced with a search engine than the classical binary precision metric. The parameter &lt;em&gt;p&lt;/em&gt; models the desperation of the user and can vary to fit your problem domain. I personally like p=50%, because it makes for nice numbers, but it should proabably be chosen based on sampling based on knowledge of the search domain.&lt;/p&gt;
&lt;p&gt;You can of course embellish this model with a stair-step in the cost function on each page boundary, etc. — any monotone decreasing infinite series that sums to a finite number in the limit should do.&lt;/p&gt;
&lt;p&gt;A similar modification can of course be applied to recall.&lt;/p&gt;
&lt;p&gt;I used this approach a couple of years ago to help tune a search engine to good effect. I went to refer someone to this post today and I realized I hadn't posted it in the almost two years since it was written, so here it is, warts and all.&lt;/p&gt;
&lt;p&gt;If anyone is familiar with similar approaches in the literature, I'd be grateful for references!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/remodeling-precision/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Curried Scheme</title><link>https://comonad.com/reader/2009/curried-scheme/</link><guid isPermaLink="false">https://comonad.com/reader/2009/curried-scheme/</guid><pubDate>Sat, 29 Aug 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 29 August 2009&lt;/p&gt;&lt;span id=&quot;more-145&quot;&gt;&lt;/span&gt;&lt;p&gt;I've been transcoding a lot of Haskell to Scheme lately and one of the things that I found myself needing was a macro for dealing with Currying of functions in a way that handles partial and over-application cleanly.&lt;/p&gt;
&lt;p&gt;I found a very elegant &lt;a href=&quot;http://programming-musings.org/2007/02/03/scheme-code-capsule-currying/&quot;&gt;macro by Piet Delport that handles partial application&lt;/a&gt;, but that doesn't deal with the partial application of no arguments or that I'd like to also be able to say things like the following and have the extra arguments be passed along to the result.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;scheme code&quot;&gt;&lt;code class=&quot;language-scheme&quot;&gt;(&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;id&lt;/span&gt; x) x)
(&lt;span class=&quot;hljs-name&quot;&gt;id&lt;/span&gt; + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;;;=&amp;gt; 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This of course, becomes more useful for more complicated definitions.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;scheme code&quot;&gt;&lt;code class=&quot;language-scheme&quot;&gt;(&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;compose&lt;/span&gt; f g x) (&lt;span class=&quot;hljs-name&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;g&lt;/span&gt; x)))
(&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;const&lt;/span&gt; a _) a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While I could manually associate the parentheses to the left and nest lambdas everywhere, Haskell code is rife with these sorts of applications. In the spirit of Scheme, since I couldn't find a macro on the internet that did what I want, I tried my hand at rolling my own.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;scheme code&quot;&gt;&lt;code class=&quot;language-scheme&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;;; curried lambda&lt;/span&gt;
(&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;define-syntax&lt;/span&gt;&lt;/span&gt; curried
  (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;syntax-rules&lt;/span&gt;&lt;/span&gt; ()
    ((&lt;span class=&quot;hljs-name&quot;&gt;_&lt;/span&gt; () body)
     (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;hljs-name&quot;&gt;args&lt;/span&gt;
         (if (null? args)
             body
             (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;apply&lt;/span&gt;&lt;/span&gt; body args))))
    ((&lt;span class=&quot;hljs-name&quot;&gt;_&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;arg&lt;/span&gt;) body)
      (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;letrec&lt;/span&gt;&lt;/span&gt;
        ((&lt;span class=&quot;hljs-name&quot;&gt;partial-application&lt;/span&gt;
          (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;hljs-name&quot;&gt;args&lt;/span&gt;
            (if (null? args)
                partial-application
                (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;let&lt;/span&gt;&lt;/span&gt; ((&lt;span class=&quot;hljs-name&quot;&gt;arg&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;car&lt;/span&gt;&lt;/span&gt; args))
                      (&lt;span class=&quot;hljs-name&quot;&gt;rest&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cdr&lt;/span&gt;&lt;/span&gt; args)))
                  (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;null?&lt;/span&gt;&lt;/span&gt; rest)
                      body
                      (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;apply&lt;/span&gt;&lt;/span&gt; body rest)))))))
        partial-application))
    ((&lt;span class=&quot;hljs-name&quot;&gt;_&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;arg&lt;/span&gt; args ...) body)
     (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;letrec&lt;/span&gt;&lt;/span&gt;
       ((&lt;span class=&quot;hljs-name&quot;&gt;partial-application&lt;/span&gt;
         (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;hljs-name&quot;&gt;all-args&lt;/span&gt;
           (if (null? all-args)
               partial-application
               (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;let&lt;/span&gt;&lt;/span&gt; ((&lt;span class=&quot;hljs-name&quot;&gt;arg&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;car&lt;/span&gt;&lt;/span&gt; all-args))
                     (&lt;span class=&quot;hljs-name&quot;&gt;rest&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cdr&lt;/span&gt;&lt;/span&gt; all-args)))
                 (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;let&lt;/span&gt;&lt;/span&gt; ((&lt;span class=&quot;hljs-name&quot;&gt;next&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;args&lt;/span&gt; ...) body)))
                   (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;null?&lt;/span&gt;&lt;/span&gt; rest)
                       next
                       (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;apply&lt;/span&gt;&lt;/span&gt; next rest))))))))
       partial-application))))

&lt;span class=&quot;hljs-comment&quot;&gt;;; curried defines&lt;/span&gt;
(&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;define-syntax&lt;/span&gt;&lt;/span&gt; define-curried
  (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;syntax-rules&lt;/span&gt;&lt;/span&gt; ()
    ((&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;name&lt;/span&gt; args ...) body)
       (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;define&lt;/span&gt;&lt;/span&gt; name (&lt;span class=&quot;hljs-name&quot;&gt;curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;args&lt;/span&gt; ...) body)))
    ((&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; (&lt;span class=&quot;hljs-name&quot;&gt;name&lt;/span&gt;) body)
       (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;define&lt;/span&gt;&lt;/span&gt; name (&lt;span class=&quot;hljs-name&quot;&gt;curried&lt;/span&gt; () body)))
    ((&lt;span class=&quot;hljs-name&quot;&gt;define-curried&lt;/span&gt; name body)
       (&lt;span class=&quot;hljs-name&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;define&lt;/span&gt;&lt;/span&gt; name body))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While Scheme is not my usual programming language, I love the power of hygienic macros.&lt;/p&gt;
&lt;p&gt;I welcome feedback.&lt;/p&gt;
&lt;p&gt;[Edit: updated to change the base case for define-curried and added the if to the base case of curried to be more consistent with the other cases per the second comment below]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/curried-scheme/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Iteratees, Parsec and Monoids (Slides)</title><link>https://comonad.com/reader/2009/iteratees-parsec-and-monoid/</link><guid isPermaLink="false">https://comonad.com/reader/2009/iteratees-parsec-and-monoid/</guid><pubDate>Thu, 20 Aug 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 20 August 2009&lt;/p&gt;&lt;p&gt;I was asked to give two talks at the &lt;a href=&quot;http://groups.google.com/group/bostonhaskell&quot;&gt;Boston Area Haskell User Group&lt;/a&gt; for this past Tuesday. The first was pitched at a more introductory level and the second was to go deeper into what I have been using monoids for lately.&lt;/p&gt;
&lt;p&gt;The first talk covers an introduction to the mathematical notion of a monoid, introduces some of the features of my Haskell monoids library on hackage, and starts to motivate the use of monoidal parallel/incremental parsing, and the modification use of compression algorithms to recycle monoidal results.&lt;/p&gt;
&lt;p&gt;The second talk covers a way to generate a locally-context sensitive parallel/incremental parser by modifying &lt;a href=&quot;http://okmij.org/ftp/Haskell/Iteratee/Iteratee.hs&quot;&gt;Iteratees&lt;/a&gt; to enable them to drive a &lt;a href=&quot;https://hackage.haskell.org/package/parsec-3.0.0&quot;&gt;Parsec 3&lt;/a&gt; lexer, and then wrapping that in a monoid based on &lt;a href=&quot;http://dragonbook.stanford.edu/lecture-notes/Columbia-COMS-W4115/08-03-05.html&quot;&gt;error productions&lt;/a&gt; in the grammar before recycling these techniques at a higher level to deal with parsing seemingly stateful structures, such as Haskell layout.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/imported/371d14b95499-IntroductionToMonoids.pdf&quot;&gt;Introduction To Monoids (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/imported/f22c2509176c-A-Parsing-Trifecta.pdf&quot;&gt;Iteratees, Parsec and Monoids: A Parsing Trifecta (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Due to a late start, I was unable to give the second talk. However, I did give a quick run through to a few die-hards who stayed late and came to the &lt;a href=&quot;http://www.cambrew.com/&quot;&gt;Cambridge Brewing Company&lt;/a&gt; afterwards. As I promised some people that I would post the slides after the talk, here they are.&lt;/p&gt;
&lt;p&gt;The current plan is to possibly give the second talk in full at either the September or October Boston Haskell User Group sessions, depending on scheduling and availability.&lt;/p&gt;
&lt;p&gt;[ &lt;a href=&quot;https://comonad.com/assets/imported/9386c70e357e-Iteratee.hs&quot;&gt;Iteratee.hs&lt;/a&gt; ]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/iteratees-parsec-and-monoid/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Clearer Reflections</title><link>https://comonad.com/reader/2009/clearer-reflection/</link><guid isPermaLink="false">https://comonad.com/reader/2009/clearer-reflection/</guid><pubDate>Sat, 15 Aug 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 15 August 2009&lt;/p&gt;&lt;span id=&quot;more-93&quot;&gt;&lt;/span&gt;&lt;p&gt;I have updated the &lt;a href=&quot;https://hackage.haskell.org/package/reflection-0.2.0&quot;&gt;reflection&lt;/a&gt; package on hackage to use &lt;a href=&quot;http://www.haskell.org/pipermail/haskell-cafe/2009-August/065237.html&quot;&gt;an idea for avoiding dummy arguments&lt;/a&gt; posted to the &lt;a href=&quot;http://www.haskell.org/mailman/listinfo/haskell-cafe&quot;&gt;Haskell cafe mailing list&lt;/a&gt; by Bertram Felgenhauer, which adapts nicely to the case of handling Reflection. The reflection package implements the ideas from the &lt;a href=&quot;http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf&quot;&gt;Functional Pearl: Implicit Configurations&lt;/a&gt; paper by Oleg Kiselyov and Chung-chieh Shan.&lt;/p&gt;
&lt;p&gt;Now, you no longer need to use big scary undefineds throughout your code and can instead program with implicit configurations more naturally, using Applicative and Monad sugar.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;Data&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Reflection&lt;/span&gt;&amp;gt; reify (+)
    (reflect &amp;lt; *&amp;gt; pure &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt; *&amp;gt; (reflect &amp;lt; *&amp;gt; pure &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &amp;lt; *&amp;gt; pure &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;))
&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Monad in question just replaces the lambda with a phantom type parameter, enabling the compiler to more readily notice that no instance can actually even try to use the value of the type parameter.&lt;/p&gt;
&lt;p&gt;An &lt;a href=&quot;http://www.mail-archive.com/haskell-cafe@haskell.org/msg57747.html&quot;&gt;example from the old API&lt;/a&gt; can be seen on the Haskell cafe.&lt;/p&gt;
&lt;p&gt;This example can be made appreciably less scary now!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, Rank2Types,
     FlexibleContexts, UndecidableInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Applicative
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Reflection
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Tagged

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; s (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; → &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; → &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) ⇒ &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    mempty = tagMonoid $ fst &amp;lt; $&amp;gt; reflect
    a `mappend` b = tagMonoid $
        snd &amp;lt; $&amp;gt; reflect &amp;lt; *&amp;gt; monoidTag a &amp;lt; *&amp;gt; monoidTag b

&lt;span class=&quot;hljs-title&quot;&gt;monoidTag&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; s a → &lt;span class=&quot;hljs-type&quot;&gt;Tagged&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;monoidTag&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Tagged&lt;/span&gt; a

&lt;span class=&quot;hljs-title&quot;&gt;tagMonoid&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Tagged&lt;/span&gt; s a → &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; s a
&lt;span class=&quot;hljs-title&quot;&gt;tagMonoid&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tagged&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; a

&lt;span class=&quot;hljs-title&quot;&gt;withMonoid&lt;/span&gt; :: a → (a → a → a) →
    (∀s. &lt;span class=&quot;hljs-type&quot;&gt;Reifies&lt;/span&gt; s (a, a → a → a) ⇒ &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; s w) → w
&lt;span class=&quot;hljs-title&quot;&gt;withMonoid&lt;/span&gt; e op m = reify (e,op) (monoidTag m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with that we can cram a Monoid dictionary -- or any other -- with whatever methods we want and our safety is assured by parametricity due to the rank 2 type, just like with the ST monad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&amp;gt; withMonoid &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; (+) (&lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; `mappend` &lt;span class=&quot;hljs-type&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; `mappend` mempty)
&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[Edit: factored Tagged out into Data.Tagged in a separate package, and modified reflection to use that instead, with an appropriate version bump to satisfy the package versioning policy]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/clearer-reflection/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Slides from Hac Phi: “All About Monoids”</title><link>https://comonad.com/reader/2009/hac-phi-slides/</link><guid isPermaLink="false">https://comonad.com/reader/2009/hac-phi-slides/</guid><pubDate>Fri, 31 Jul 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 31 July 2009&lt;/p&gt;&lt;p&gt;Some people have requested my slides from the short talk I gave about monoids and monoidal parsing at Hac Phi. So, here they are.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/imported/48518a1e657a-AllAboutMonoids.pptx&quot;&gt;Hac Phi Slides (Powerpoint 2007)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/assets/imported/d583072ab156-AllAboutMonoids.pdf&quot;&gt;Hac Phi Slides (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There will be more to come at the next Boston Haskell User Group in August, where it looks like I'll be giving two short talks covering monoids. I may use the monoidal parsing engine from Kata as an example for the advanced talk if I have time and will start to cover parsing larger classes of grammars in general (regular languages, CFGs/TIGs, TAGs, PEGs, LALR, attribute-grammars, etc.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/hac-phi-slides/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Recursion Schemes: A Field Guide (Redux)</title><link>https://comonad.com/reader/2009/recursion-schemes/</link><guid isPermaLink="false">https://comonad.com/reader/2009/recursion-schemes/</guid><pubDate>Thu, 11 Jun 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 11 June 2009&lt;/p&gt;&lt;p&gt;About a year back I posted a field guide of recursion schemes on this blog and then lost it a few months later when I lost a couple of months of blog entries to a &lt;a href=&quot;https://comonad.com/reader/2008/still-alive/&quot;&gt;crash&lt;/a&gt;. I recently recovered the table of recursion schemes from the original post thanks to &lt;a href=&quot;http://www.google.com/reader/&quot;&gt;Google Reader&lt;/a&gt;'s long memory and the help of Jeff Cutsinger.&lt;/p&gt;
&lt;p&gt;The following recursion schemes can be found in &lt;a href=&quot;https://hackage.haskell.org/package/category-extras&quot;&gt;category-extras&lt;/a&gt;, along with variations on the underlying themes, so this should work as a punch-list.&lt;/p&gt;
&lt;table border=&quot;1&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th colspan=&quot;3&quot;&gt;Folds&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Scheme&lt;/th&gt;&lt;th&gt;Code&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://knol.google.com/k/edward-kmett/catamorphisms/&quot;&gt;catamorphism&lt;/a&gt;†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Cata.hs&quot;&gt;Cata&lt;/a&gt;&lt;/td&gt;&lt;td&gt;tears down a structure level by level&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;paramorphism*†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Para.hs&quot;&gt;Para&lt;/a&gt;&lt;/td&gt;&lt;td&gt;tears down a structure with primitive recursion&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;zygomorphism*†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Zygo.hs&quot;&gt;Zygo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;tears down a structure with the aid of a helper function&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;histomorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Histo.hs&quot;&gt;Histo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;tears down a structure with the aid of the previous answers it has given.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;prepromorphism*†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Prepro.hs&quot;&gt;Prepro&lt;/a&gt;&lt;/td&gt;&lt;td&gt;tears down a structure after repeatedly applying a natural transformation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th colspan=&quot;3&quot;&gt;Unfolds&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Scheme&lt;/th&gt;&lt;th&gt;Code&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;anamorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Ana.hs&quot;&gt;Ana&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure level by level&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;apomorphism*†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Apo.hs&quot;&gt;Apo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure opting to return a single level or an entire branch at each point&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;futumorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Futu.hs&quot;&gt;Futu&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure multiple levels at a time&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;postpromorphism*†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Postpro.hs&quot;&gt;Postpro&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure and repeatedly transforms it with a natural transformation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th colspan=&quot;3&quot;&gt;Refolds&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Scheme&lt;/th&gt;&lt;th&gt;Code&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;hylomorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Hylo.hs&quot;&gt;Hylo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up and tears down a virtual structure&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;chronomorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Chrono.hs&quot;&gt;Chrono&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a virtual structure with a futumorphism and tears it down&lt;br&gt;with a histomorphism&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synchromorphism&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Synchro.hs&quot;&gt;Synchro&lt;/a&gt;&lt;/td&gt;&lt;td&gt;a high level transformation between data structures using a third data structure to queue intermediate results&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;exomorphism&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Exo.hs&quot;&gt;Exo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;a high level transformation between data structures from a trialgebra to a bialgebraga&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;metamorphism&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Meta/Erwig.hs&quot;&gt;Erwig&lt;/a&gt;&lt;/td&gt;&lt;td&gt;a hylomorphism expressed in terms of bialgebras&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;metamorphism&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Meta/Gibbons.hs&quot;&gt;Gibbons&lt;/a&gt;&lt;/td&gt;&lt;td&gt;A fold followed by an unfold; change of representation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dynamorphism†&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Morphism/Dyna.hs&quot;&gt;Dyna&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a virtual structure with an anamorphism and tears it down with a histomorphism&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://arxiv.org/abs/cs/0609040&quot;&gt;Elgot algebra&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Functor/Algebra/Elgot.hs&quot;&gt;Elgot&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure and tears it down but may shortcircuit the process during construction&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/reader/2008/elgot-coalgebras/&quot;&gt;Elgot coalgebra&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Functor/Algebra/Elgot.hs&quot;&gt;Elgot&lt;/a&gt;&lt;/td&gt;&lt;td&gt;builds up a structure and tears it down but may shortcircuit the process during deconstruction&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;* This gives rise to a family of related recursion schemes, modeled in category-extras with distributive law combinators&lt;br&gt;
† The scheme can be generalized to accept one or more F-distributive (co)monads.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/recursion-schemes/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Reflecting On Incremental Folds</title><link>https://comonad.com/reader/2009/incremental-folds/</link><guid isPermaLink="false">https://comonad.com/reader/2009/incremental-folds/</guid><pubDate>Tue, 31 Mar 2009 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 31 March 2009&lt;/p&gt;&lt;span id=&quot;more-83&quot;&gt;&lt;/span&gt;&lt;p&gt;Recently, Sean Leather took up the idea of incremental folds. &lt;a href=&quot;http://splonderzoek.blogspot.com/2009/02/incremental-fold-design-pattern.html&quot;&gt;[1]&lt;/a&gt; &lt;a href=&quot;http://splonderzoek.blogspot.com/2009/03/incremental-attributes.html&quot;&gt;[2]&lt;/a&gt;. At the end of his first article on the topic he made a comment on how this was a useful design pattern and sagely noted the advice of Jeremy Gibbons that design patterns are more effective as programs, while complaining of cut and paste coding issues.&lt;/p&gt;
&lt;p&gt;The following attempts to address these concerns.&lt;/p&gt;
&lt;p&gt;Below, I'm going to be using two libraries which I haven't mentioned on here before:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My &lt;a href=&quot;https://hackage.haskell.org/package/monoids&quot;&gt;monoids&lt;/a&gt; library which contains among other things a large supply of monoids and the concept of a &lt;a href=&quot;https://comonad.com/haskell/monoids/dist/doc/html/monoids/Data-Monoid-Reducer.html&quot;&gt;Reducer&lt;/a&gt;. A 'Reducer' is a monoid that knows how to inject values from another type. It also supports efficient left-to-right and right-to-left reduction, but we will be availing ourselves of neither of those extra faculties at the moment.&lt;/li&gt;
&lt;li&gt;The other library is &lt;a href=&quot;https://hackage.haskell.org/package/reflection&quot;&gt;reflection&lt;/a&gt;, which is a transcoding of Oleg Kiselyov and Chung-chieh Shan's incredibly elegant approach from &lt;a href=&quot;http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf&quot;&gt;&quot;Functional Pearl: Implicit Configurations&quot;&lt;/a&gt; updated slightly to work with the changes in GHC's implementation of ScopedTypeVariables since the article was written.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The source code for this post is available as &lt;a href=&quot;https://comonad.com/haskell/Incremental.hs&quot;&gt;Incremental.hs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The 'monoids' and 'reflection' libraries are available from hackage.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE
   TypeOperators
 , MultiParamTypeClasses
 , FlexibleInstances
 , FlexibleContexts
 , UndecidableInstances
 , ScopedTypeVariables
 , GeneralizedNewtypeDeriving
 #-}&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Incremental &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Show
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Text.Read
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Reflection
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid.Reducer &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;getSum&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;ReducedBy&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;Reduction&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;getReduction&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[Edit: updated to hide a few more things from Data.Monoid.Reducer which now contains a 'ReducedBy' constructor, which serves a different purpose.]&lt;/p&gt;
&lt;p&gt;I want to take a bit of a different tack than I did with 'category-extras' and define algebras and coalgebras as type classes.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi :: f m -&amp;gt; m
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coalgebra&lt;/span&gt; f m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    psi :: m -&amp;gt; f m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that if you need to use a different Algebra, apply a newtype wrapper to the value m. We'll fix this requirement to some degree later on in this post.&lt;/p&gt;
&lt;p&gt;Now, for every Functor, we can reduce it to ().&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f () &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi _ = ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can define the idea of an F-Algebra product&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- F-Algebra product&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi a = (phi (fmap fst a), phi (fmap snd a))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;)
  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;n&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;o&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi a = (phi (fmap f a),phi (fmap g a),phi (fmap h a)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
        f (x,_,_) = x
        g (_,y,_) = y
        h (_,_,z) = z
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and so on for larger tuples.&lt;/p&gt;
&lt;p&gt;From there, the usual direction would be to define a fixpoint operator in one of several ways, so not to disappoint:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; f == &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; g = f == g
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; f `compare` &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; g = f `compare` g
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showsPrec d (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; f) = showParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;) $
        showString &lt;span class=&quot;hljs-string&quot;&gt;&quot;In &quot;&lt;/span&gt; . showsPrec &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt; f
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    readPrec = parens . prec &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;Ident&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;In &quot;&lt;/span&gt; &amp;lt; - lexP
        f &amp;lt;- step readPrec
        return (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can define an Algebra and Coalgebra for getting into and out of this fixed point.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi = &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coalgebra&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    psi (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; x) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But our goal is an incremental fold without boilerplate. So I'd rather than the fixed point operator did the heavy lifting for me.&lt;/p&gt;
&lt;p&gt;So lets define an alternative fixedpoint, in which we'll carry around an extra term for the result of applying the incremental Algebra so far.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) = f (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) :&amp;gt; m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The much more categorically inclined members of the audience may recognize that immediately as the 'cofree' comonad of f from category-extras, and in fact we could continue on adding that definition, and turn it into a comonad for any Functor. I leave that as an exercise for the interested reader, but what we are interested in is the 'extract' operation of that comonad, which we'll just call value for now.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; :: (f :&amp;gt; m) -&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt; (_ :&amp;gt; m) = m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The particularly observant may further note that value itself is an (f :&amp;gt;)-algebra, since the 'extract' operation of any copointed functor f is just an f-algebra.&lt;/p&gt;
&lt;p&gt;First, we add some boilerplate in the fashion of Mu f above.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    f :&amp;gt; m == g :&amp;gt; n = f == g &amp;amp;&amp;amp; m == n
    f :&amp;gt; m /= g :&amp;gt; n = f /= g || m /= n
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    (f :&amp;gt; m) `compare` (g :&amp;gt; n) | a == &lt;span class=&quot;hljs-type&quot;&gt;EQ&lt;/span&gt; = m `compare` n
                                | otherwise = a
        &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; a = f `compare` g
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showsPrec d (f :&amp;gt; m) = showParen (d &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;) $
        showsPrec &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; f .
        showString &lt;span class=&quot;hljs-string&quot;&gt;&quot; :&amp;gt; &quot;&lt;/span&gt; .
        showsPrec &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; m
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    readPrec = parens $ prec &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
            f &amp;lt; - step readPrec
            &lt;span class=&quot;hljs-type&quot;&gt;Symbol&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;:&amp;gt;&quot;&lt;/span&gt; &amp;lt; - lexP
            m &amp;lt;- step readPrec
            return (f :&amp;gt; m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then we note that we can ask for the 'tail' of any cofree comonad as well, which gives us a more immediately useful coalgebra.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Coalgebra&lt;/span&gt; f (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    psi (x :&amp;gt; _) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now, we come back to why we made algebras and coalgebras into a typeclass in the first place. We can define an algebra for how we propagate the information from another algebra that we want to incrementally apply to our functor f.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi x = x :&amp;gt; phi (fmap value x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can give these convenient names so we don't get our phi's and psi's confused.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;forget&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f :&amp;gt; m) -&amp;gt; f (f :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;forget&lt;/span&gt; = psi

&lt;span class=&quot;hljs-title&quot;&gt;remember&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f m =&amp;gt; f (f :&amp;gt; m) -&amp;gt; f :&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;remember&lt;/span&gt; = phi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;'forget' discards the wrapper which contains the result of having applied our algebra.&lt;/p&gt;
&lt;p&gt;'remember' takes an f (f :&amp;gt; m) and adds a wrapper, which remembers the result of having applied our selected f-algebra with carrier m.&lt;/p&gt;
&lt;p&gt;With these convenient aliases, we can define catamorphisms and anamorphisms over (f :&amp;gt; m).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f a =&amp;gt; (f :&amp;gt; m) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; = phi . fmap cata . forget

&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f m, &lt;span class=&quot;hljs-type&quot;&gt;Coalgebra&lt;/span&gt; f a) =&amp;gt; a -&amp;gt; (f :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;ana&lt;/span&gt; = remember . fmap ana . psi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;cata just forgets the wrapper, and applies an algebra recursively as usual.&lt;/p&gt;
&lt;p&gt;On the other hand, our anamorphism now needs to know the algebra for the incremental fold, so that it can apply it as it builds up our new structure.&lt;/p&gt;
&lt;p&gt;We can easily go back and forth between our two fixed point representations.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;tag&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; (f :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;tag&lt;/span&gt; = remember . fmap tag . psi

&lt;span class=&quot;hljs-title&quot;&gt;untag&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f :&amp;gt; m) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;untag&lt;/span&gt; = phi . fmap untag . forget
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, with that machinery in hand, lets try to build a couple of examples, and then see if we can push the envelope a little further.&lt;/p&gt;
&lt;p&gt;So lets define the binary tree that Sean has been using, except now as a base functor that we'll fold.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a r = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; r a r | &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x a y) = &lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (f x) a (f y)
    fmap _ &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As with Sean's code, we'll use a pair of smart constructors to build our tree, but note, we no longer have the unsightly and easily mistaken explicit algebra arguments. You can no longer mistakenly apply the wrong algebra!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) m =&amp;gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a :&amp;gt; m) -&amp;gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a :&amp;gt; m) -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;bin&lt;/span&gt; a v b = remember (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; a v b)

&lt;span class=&quot;hljs-title&quot;&gt;tip&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) m =&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;tip&lt;/span&gt; = remember &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, we'll need some data to play with, so lets define a nice generic looking tree.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;testTree&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a) m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; a :&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;testTree&lt;/span&gt; = bin tip &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (bin (bin tip &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; tip) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; tip)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And while we're at it lets define a couple of algebras to try things out.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getSize&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x _ y) = x + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + y
    phi &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getSum&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x y z) = x + &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; y + z
    phi &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With those we can now rush off to ghci and give it a whirl.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;Incremental&lt;/span&gt;&amp;gt; testTree :: &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;})
    &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
    (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt;
        (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt;
            (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;})
            &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;
            (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;})
            :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;}
        )
        &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;
        (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;})
        :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;}
    ) :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; {getSum = &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that each node in the tree is tagged with the accumulated result of our algebra.&lt;/p&gt;
&lt;p&gt;Of course, since we also have an f-algebra with carrier Mu f, we can ask for that to be computed incrementally as well.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;Incremental&lt;/span&gt;&amp;gt; testTree :: &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;)
&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;)
:&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt;
(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))) :&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt;
(&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))) &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;In&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt;))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, this prints very poorly, but shares heavily as you can see below thanks to &lt;a href=&quot;https://hackage.haskell.org/package/vacuum&quot;&gt;vacuum&lt;/a&gt; by Matt Morrow.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/haskell/tree.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, defining Sum, and Size manually may be all well and good, and its sure a lot less work than it was before, but we can also just decide to lift almost any Monoid into an f-Algebra. Here is where we need the 'Reducer' concept from 'monoids' that was mentioned earlier.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; m = &lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getMon&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Reducer&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Bin&lt;/span&gt; x v y) = x `mappend` &lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; (unit v) `mappend` y
    phi &lt;span class=&quot;hljs-type&quot;&gt;Tip&lt;/span&gt; = mempty
    &lt;span class=&quot;hljs-comment&quot;&gt;-- where unit :: (a `Reducer`m) =&amp;gt; a -&amp;gt; m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, we're not limited to trees.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a r = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a r | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a x) = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a (f x)
    fmap _ &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; _ xs) = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + xs
    phi &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;hljs-type&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x xs) = fromIntegral x + xs
    phi &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Reducer&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; x xs) = &lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; (unit x) `mappend` xs
    phi &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = mempty

&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a) m =&amp;gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m) -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m)
&lt;span class=&quot;hljs-title&quot;&gt;cons&lt;/span&gt; a b = remember (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a b)

&lt;span class=&quot;hljs-title&quot;&gt;nil&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a) m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;nil&lt;/span&gt; = remember &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;testList&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a) m) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;testList&lt;/span&gt; = cons &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; . cons &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; . cons &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; $ cons &lt;span class=&quot;hljs-number&quot;&gt;27&lt;/span&gt; nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now we're at a bit of an impasse. How do you deal with f-algebras that use some environment? When writing these out by hand, if a particular algebra uses a variable that is in scope it just closes over it in its environment. Giving a reference to the carrier for the algebra permits the abstraction to leak, and most likely requires you to regress to a smart constructor approach in which you package up that extra information by hand.&lt;/p&gt;
&lt;p&gt;Since we package up the algebra in a type class, we seem, at first glance to have lost the ability to access an environment. After all a 'benefit' of the looser types permitted by Sean's post was that he could build values using an arbitrary algebra, just using any old pair of functions.&lt;/p&gt;
&lt;p&gt;One useful example that would seem at first glance to be ruled out is the following. Every different filter function would have to be a different algebra!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;filter_phi&lt;/span&gt; ::
    &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a) m =&amp;gt;
    (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bool&lt;/span&gt;) -&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a :&amp;gt; m
&lt;span class=&quot;hljs-title&quot;&gt;filter_phi&lt;/span&gt; p &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; = nil
&lt;span class=&quot;hljs-title&quot;&gt;filter_phi&lt;/span&gt; p (&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
    | p a = cons a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
    | otherwise = &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, lets do just that. We need to be able to reify an arbitrary function from a term into a type and we can do this with Data.Reflection! For the technical details, please read Oleg and Chung-chieh's very elegant functional pearl, but the idea is that by carefully abusing the ability to convert a list of integers into a type, we can convert a stable pointer into a type and share it in a limited context. In this case, that stable pointer can point to our particular algebra, environment and all, and yet we can be sure that the user doesn't try to mix incremental folds that use different environments.&lt;/p&gt;
&lt;p&gt;To do this, we need a phantom type parameter in the carrier for our f-algebra.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;ReducedBy&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Reduction&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;getReduction&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and to reflect the function back down from the type level in our f-algebra.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;Reflects&lt;/span&gt;` (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Algebra&lt;/span&gt; f (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;ReducedBy&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    phi = &lt;span class=&quot;hljs-type&quot;&gt;Reduction&lt;/span&gt; . reflect (undefined :: s) . fmap getReduction
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that we can define any f-algebra that needs context, by reflecting it into the type system. The rank-2 type protects us from trying to put together data structures that were constructed using different algebras.&lt;/p&gt;
&lt;p&gt;So now we can now apply this particular algebra to filter a list incrementally build up a list which incrementally builds itself in the [Int] monoid and tracks its length. Here we'll filter the list from earlier for even numbers and apply these other incremental operations all in one go. It reads a little more naturally if broken into parts, but we can write this all in one go.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; :&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;],&lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt;)
&lt;span class=&quot;hljs-title&quot;&gt;test&lt;/span&gt; = reify
    (filter_phi (\x -&amp;gt; x `mod` &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;))
    (\\(_ :: s) -&amp;gt;
      getReduction (
        value (
          testList :: &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; :&amp;gt;
            ((&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; :&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; [&lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;],&lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt;)) `&lt;span class=&quot;hljs-type&quot;&gt;ReducedBy&lt;/span&gt;` s))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which we can test out:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;Incremental&lt;/span&gt;&amp;gt; test
&lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; (
    &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt; (
        &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; :&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; {getMon = []},&lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; {getSize = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;})
    ) :&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; {getMon = [&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]},&lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; {getSize = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;})
) :&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mon&lt;/span&gt; {getMon = [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]},&lt;span class=&quot;hljs-type&quot;&gt;Size&lt;/span&gt; {getSize = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there you have an incremental fold upon reflection.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://comonad.com/haskell/Incremental.hs&quot;&gt;Incremental.hs&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/haskell/reflection/Data/Reflection.hs&quot;&gt;Data/Reflection.hs&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/haskell/monoids/dist/doc/html/monoids/src/Data-Monoid-Reducer.html&quot;&gt;Data/Monoid/Reducer.hs&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2009/incremental-folds/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The Pointed-Set Comonad</title><link>https://comonad.com/reader/2008/the-pointed-set-comonad/</link><guid isPermaLink="false">https://comonad.com/reader/2008/the-pointed-set-comonad/</guid><pubDate>Thu, 04 Dec 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 4 December 2008&lt;/p&gt;&lt;span id=&quot;more-80&quot;&gt;&lt;/span&gt;&lt;p&gt;Last night, Chung-Chieh Shan posted an example of a &lt;a href=&quot;http://conway.rutgers.edu/~ccshan/wiki/blog/posts/Pointed_set/&quot;&gt;pointed-set monad&lt;/a&gt; on his blog, which happens to be isomorphic to a non-empty stream monad with a different emphasis.&lt;/p&gt;
&lt;p&gt;But, I thought I should point out that the pointed set that he posted also has a comonadic structure, which may be exploited since it is just a variation on the &quot;zipper comonad,&quot; a structure that is perhaps more correctly called a &quot;pointing comonad.&quot;&lt;/p&gt;
&lt;p&gt;But first, a little background:&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;http://en.wikipedia.org/wiki/Combinatorial_species&quot;&gt;combinatorial species&lt;/a&gt; you point a data structure by marking a single element in it as special. We can represent that with the product of an element and the &lt;a href=&quot;http://en.wikipedia.org/wiki/Derivative_(generalizations)#Set_theory_and_logic&quot;&gt;derivative&lt;/a&gt; of the original type.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;*[&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;] = &lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt; * &lt;span class=&quot;hljs-type&quot;&gt;F'&lt;/span&gt;[&lt;span class=&quot;hljs-type&quot;&gt;A&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, then looking at Shan's pointed set, we can ask what combinatorial species has a list as its derivative?&lt;/p&gt;
&lt;p&gt;The answer is a cycle, not a set.&lt;/p&gt;
&lt;p&gt;This fact doesn't matter to the monad, since the only way a monadic action interacts with that extra structure is safely through bind, but does for the comonad where every comonadic action has access to that structure, but no control over the shape of the result.&lt;/p&gt;
&lt;p&gt;However, we don't really have a way to represent an unordered set in Haskell, so if you are treating a list as a set, the derivative of a set is another set then we can also view the a * [a] as a pointed set, so long as we don't depend on the order of the elements in the list in any way in obtaining the result of our comonadic actions.&lt;/p&gt;
&lt;p&gt;I've changed the name of his data type to &lt;code&gt;PointedSet&lt;/code&gt; to avoid conflicting with the definitions of &lt;code&gt;Pointed&lt;/code&gt; and &lt;code&gt;Copointed&lt;/code&gt; functors in category extras.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; PointedSet &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Comonad &lt;span class=&quot;hljs-comment&quot;&gt;-- from my category-extras library&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.List (&lt;span class=&quot;hljs-title&quot;&gt;inits&lt;/span&gt;,&lt;span class=&quot;hljs-title&quot;&gt;tails&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- used much later below&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a [a] &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; x xs) = &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; (f x) $ fmap f xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition for extract is obvious, since you have already selected a point, just return it.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Copointed&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    extract (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; x _) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other hand, for duplicate we have a couple of options. An obvious and correct, but boring implementation transforms a value as follows:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;boring_duplicate&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;boring_duplicate&lt;/span&gt; xxs@(&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; x xs) =
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; xxs $ fmap (flip &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; []) xs
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt;&amp;gt; boring_duplicate $ &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]
&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]) [
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; [],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; [],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; []
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but that just abuses the fact that we can always return an empty list.&lt;/p&gt;
&lt;p&gt;Another fairly boring interpretation is to just use the guts of the definition of the Stream comonad, but that doesn't model a set with a single memory singled out.&lt;/p&gt;
&lt;p&gt;A more interesting version refocuses on each element of the list in turn, which makes the connection to the zipper comonad much more obvious. Since we want a pointed set and not a pointed cycle, we can focus on an element just by swapping out the element in the list in that position for the focus.&lt;/p&gt;
&lt;p&gt;Again, since we can't specify general species in Haskell, this is as close as we can come to the correct comonadic structure for a pointed set. Due to the limitations of our type system, the comonadic action can still see the order of elements in the set, but it shouldn't use that information.&lt;/p&gt;
&lt;p&gt;Since we don't care to preserve the order of the miscellaneous set elements, the &lt;code&gt;refocus&lt;/code&gt; helper function below can just accumulate preceding elements in an accumulating parameter in reverse order.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    duplicate xxs@(&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; x xs) = &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; xxs $ refocus [] x xs
      &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
        refocus :: [a] -&amp;gt; a -&amp;gt; [a] -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a]
        refocus acc x (y:ys) =
            &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; y (acc ++ (x:ys)) : refocus (y:acc) x ys
        refocus acc x [] = []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt;&amp;gt; duplicate $ &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;] =
&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]) [
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that in hand we can define comonadic actions that can look at an entire &lt;code&gt;PointedSet&lt;/code&gt; and return a value, then extend them comonadically to generate new pointed sets.&lt;/p&gt;
&lt;p&gt;For instance, if we had a numerical pointed set and wanted to blur our focus somewhat we could weight an average between the focused and unfocused elements:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;smooth&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Fractional&lt;/span&gt; a =&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;smooth&lt;/span&gt; w (&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) =
    w * a +
    (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; - w) * sum &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; / fromIntegral (length &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Smoothing is a safe pointed-set comonadic operation because it doesn't care about the order of the elements in the list.&lt;/p&gt;
&lt;p&gt;And so now we can blur the distinction between the focused element and the rest of the set:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt;&amp;gt; extend (smooth &lt;span class=&quot;hljs-number&quot;&gt;0.5&lt;/span&gt;) $ &lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]
&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;6.5&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;2.9&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3.3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3.7&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4.1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;4.5&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A quick pass over the comonad laws shows that they all check out.&lt;/p&gt;
&lt;p&gt;As noted above, if your comonadic action uses the order of the elements in the list beyond the selection of the focus, then it isn't really a valid pointed set comonadic operation. This is because we are abusing a list to approximate a (multi)set.&lt;/p&gt;
&lt;h2 id=&quot;the-pointed-cycle-comonad&quot;&gt;The Pointed-Cycle Comonad&lt;/h2&gt;
&lt;p&gt;A slight variation on this theme keeps the order of the elements the same in exchange for a more expensive refocusing operation and just rotates them through the focus.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; a [a] &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Ord&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;,&lt;span class=&quot;hljs-type&quot;&gt;Read&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f (&lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; x xs) = &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; (f x) $ fmap f xs
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Copointed&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    extract (&lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; x _) = x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   duplicate xxs@(&lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; x xs) =
        &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; xxs . fmap listToCycle . tail $ rotations (x:xs)
     &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
        rotations :: [a] -&amp;gt; [[a]]
        rotations xs = init $ zipWith (++) (tails xs) (inits xs)
        listToCycle (x:xs) = &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; x xs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that you acknowledge that you really have a pointed cycle and the writer of the comonadic action can safely use the ordering information intrinsic to the list as a natural consequence of having taken the derivative of a cycle.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;*&lt;span class=&quot;hljs-type&quot;&gt;PointedSet&lt;/span&gt;&amp;gt; duplicate $ &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]
&lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]) [
    &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;],
    &lt;span class=&quot;hljs-type&quot;&gt;PointedCycle&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/the-pointed-set-comonad/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Still Alive</title><link>https://comonad.com/reader/2008/still-alive/</link><guid isPermaLink="false">https://comonad.com/reader/2008/still-alive/</guid><pubDate>Sat, 08 Nov 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 8 November 2008&lt;/p&gt;&lt;p&gt;To those that have asked, I'm still alive.&lt;/p&gt;
&lt;p&gt;I had to restore the blog database from a backup and so I lost a few posts, including the index for the various recursion schemes entries. Fortunately, before that happened I had replicated the &lt;a href=&quot;http://knol.google.com/k/edward-kmett/catamorphisms/&quot;&gt;catamorphism post as a knol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Should I find myself with a copious glut of free time, I shall happily re-scribe and finish the rest, but I've been very busy.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/still-alive/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Representing Adjunctions</title><link>https://comonad.com/reader/2008/representing-adjunctions/</link><guid isPermaLink="false">https://comonad.com/reader/2008/representing-adjunctions/</guid><pubDate>Thu, 05 Jun 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 5 June 2008&lt;/p&gt;&lt;span id=&quot;more-67&quot;&gt;&lt;/span&gt;&lt;p&gt;I've had a few people ask me questions about Adjunctions since my &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;recent post&lt;/a&gt; and a request for some more introductory material, so I figured I would take a couple of short posts to tie Adjunctions to some other concepts.&lt;/p&gt;
&lt;h2 id=&quot;representable-functors&quot;&gt;Representable Functors&lt;/h2&gt;
&lt;p&gt;A covariant functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathcal{C} \to \mathbf{Set}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is said to be &lt;a href=&quot;http://en.wikipedia.org/wiki/Representable_functor&quot;&gt;representable&lt;/a&gt; by an object &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x \in \mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.5782em;vertical-align:-0.0391em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;∈&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; if it is naturally isomorphic to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hom}_C(x,-)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hom&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We can translate that into Haskell, letting &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; play the role of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Set}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; f x &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    rep :: (x -&amp;gt; a) -&amp;gt; f a
    unrep :: f a -&amp;gt; (x -&amp;gt; a)

&lt;span class=&quot;hljs-meta&quot;&gt;{-# RULES
&quot;rep/unrep&quot; rep . unrep = id
&quot;unrep/rep&quot; unrep . rep = id
 #-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is trivial to show that any two representations of a given functor must be isomorphic, and that there is a natural isomorphism between any two functors with the same representation, so we could strengthen the signature of the type class above by adding a pair of functional dependencies: f -&amp;gt; x, x -&amp;gt; f, but lets work without this straightjacket for now.&lt;/p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;
&lt;p&gt;We can represent the anonymous reader monad with its environment.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; ((-&amp;gt;)x) x &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    rep = id
    unrep = id
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;example-2&quot;&gt;Example&lt;/h2&gt;
&lt;p&gt;We could adopt the pleasant fiction that () has a single inhabitant to avoid bringing in an empty type, but lets do this correctly. Clearly the Identity functor needs no extra information from its representation.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt; {- &lt;span class=&quot;hljs-title&quot;&gt;you'll&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;need&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;EmptyDataDecls&lt;/span&gt; -}&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    rep f = &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (f undefined)
    unrep = const . runIdentity
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;adjunctions&quot;&gt;Adjunctions&lt;/h2&gt;
&lt;p&gt;If you recall the definition of Adjunctions over &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; from before:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        unit   :: a -&amp;gt; g (f a)
        counit :: f (g a) -&amp;gt; a
        leftAdjunct  :: (f a -&amp;gt; b) -&amp;gt; a -&amp;gt; g b
        rightAdjunct :: (a -&amp;gt; g b) -&amp;gt; f a -&amp;gt; b

        unit = leftAdjunct id
        counit = rightAdjunct id
        leftAdjunct f = fmap f . unit
        rightAdjunct f = counit . fmap f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can generate a lot of representable functors, by turning to the theorem mentioned in &lt;a href=&quot;http://en.wikipedia.org/wiki/Representable_functor#Left_adjoint&quot;&gt;the Wikipedia article&lt;/a&gt; about the representability of a right adjoint in terms of its left adjoint wrapped around a singleton element:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;K : \mathcal{C} \to \mathbf{Set}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with a left adjoint &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathbf{Set} \to \mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is represented by (FX, ηX(•)) where X = {•} is a singleton set and η is the unit of the adjunction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, earlier we defined a singleton set, &lt;code&gt;Void&lt;/code&gt;, and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; can play the role of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;S&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Set}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; as we did above. For &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C} = \mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, we can translate the remainder quite easily:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;repAdjunction&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; (f &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt; -&amp;gt; a) -&amp;gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;repAdjunction&lt;/span&gt; f = leftAdjunct f undefined

&lt;span class=&quot;hljs-title&quot;&gt;unrepAdjunction&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; g a -&amp;gt; (f &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt; -&amp;gt; a)
&lt;span class=&quot;hljs-title&quot;&gt;unrepAdjunction&lt;/span&gt; = rightAdjunct . const
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, as usual the way type class inference works in Haskell requires us to reason somewhat backwards.&lt;/p&gt;
&lt;p&gt;You'd like to say:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; g (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  rep = repAdjunction;
  unrep = unrepAdjunction
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if you do so, you can't define any other instances for &lt;code&gt;Representable&lt;/code&gt;, you'll have used up the instance head, so the previous definitions couldn't be made.&lt;/p&gt;
&lt;p&gt;On the other hand, you can create the obligation for an appropriate instance of &lt;code&gt;Representable&lt;/code&gt; by changing the signature of &lt;code&gt;Adjunction&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the definitions for &lt;code&gt;repAdjunction&lt;/code&gt; and &lt;code&gt;unrepAdjunction&lt;/code&gt; can be used by any would-be &lt;code&gt;Adjunction&lt;/code&gt; to automatically generate the corresponding &lt;code&gt;Representable&lt;/code&gt; instance, just like &lt;code&gt;liftM&lt;/code&gt; can alwyas be used to make a Haskell &lt;code&gt;Monad&lt;/code&gt; into a &lt;code&gt;Functor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can also go the other way and define an &lt;code&gt;Adjunction&lt;/code&gt; given a representation for the right adjoint, but I'll leave that as an exercise for the reader. (Hint: you'll probably want to weaken the signature for Adjunction to remove the fundeps, so you can test some simple cases). You may also want to take a look at the section on Adjunctions as Kan extensions portion of the &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;earlier post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have since modified &lt;a href=&quot;https://hackage.haskell.org/package/category-extras&quot;&gt;category-extras&lt;/a&gt; definition of Adjunction to require the instance for Representable motivated above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Haddock:&lt;/strong&gt;&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Adjunction.html&quot;&gt;Control.Functor.Adjunction&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Representable.html&quot;&gt;Control.Functor.Representable&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/representing-adjunctions/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Zapping Adjunctions</title><link>https://comonad.com/reader/2008/zapping-strong-adjunctions/</link><guid isPermaLink="false">https://comonad.com/reader/2008/zapping-strong-adjunctions/</guid><pubDate>Thu, 05 Jun 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 5 June 2008&lt;/p&gt;&lt;span id=&quot;more-68&quot;&gt;&lt;/span&gt;&lt;p&gt;As you may recall, every functor in Haskell is strong, in the sense that if you provided an instance of Monad for that functor the following definition would satisfy the requirements mentioned &lt;a href=&quot;http://en.wikipedia.org/wiki/Strong_monad&quot;&gt;here&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; a -&amp;gt; f b -&amp;gt; f (a,b)
&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt; = fmap . (,)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In an earlier post about &lt;a href=&quot;https://comonad.com/reader/2008/the-cofree-comonad-and-the-expression-problem/&quot;&gt;the cofree comonad and the expression problem&lt;/a&gt;, I used a typeclass defining a form of duality that enables you to let two functors annihilate each other, letting one select the path whenever the other offered up multiple options. To have a shared set of conventions with the material in &lt;a href=&quot;https://comonad.com/reader/2008/zipping-and-unzipping-functors/&quot;&gt;Zipping and Unzipping Functors&lt;/a&gt;, I have since remodeled that class slightly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zapWith :: (a -&amp;gt; b -&amp;gt; c) -&amp;gt; f a -&amp;gt; g b -&amp;gt; c
  zap :: f (a -&amp;gt; b) -&amp;gt; g a -&amp;gt; b
  zap = zapWith id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Interestingly, we can use the fact that every functor in Haskell is strong to derive not only one instance of &lt;code&gt;Zap&lt;/code&gt;, but two, given any &lt;code&gt;Adjunction&lt;/code&gt; &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f \dashv g&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I'll give one instance here:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;zapWithAdjunctionGF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; g f =&amp;gt;
    (a -&amp;gt; b -&amp;gt; c) -&amp;gt; f a -&amp;gt; g b -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;zapWithAdjunctionGF&lt;/span&gt; f a b =
    uncurry (flip f) . counit . fmap (uncurry (flip strength)) $
    strength a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And I'll leave the substantially similar derivation of the following to the reader:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;zapWithAdjunctionFG&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; (a -&amp;gt; b -&amp;gt; c) -&amp;gt; f a -&amp;gt; g b -&amp;gt; c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we would like to do the same thing we did with &lt;code&gt;Representable&lt;/code&gt; &lt;a href=&quot;https://comonad.com/reader/2008/representing-adjunctions/&quot;&gt;last time&lt;/a&gt;, and just require the user of the &lt;code&gt;Adjunction&lt;/code&gt; class to provide us with more instances, something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Representable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But there is a problem: Adjunction composition.&lt;/p&gt;
&lt;p&gt;If you will recall from before, we were able to define an instance for an &lt;code&gt;Adjunction&lt;/code&gt; for a composition of two adjunctions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;decompose&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap (fmap f) . decompose
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        counit =
               counit .
               fmap (counit . fmap decompose) .
               decompose
        unit =
               &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; .
               fmap (fmap &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . unit) .
               unit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is that we have &lt;strong&gt;three&lt;/strong&gt; different ways to build an instance of &lt;code&gt;Zap&lt;/code&gt; for this composition and we would need to define two of them that conflict!&lt;/p&gt;
&lt;p&gt;We would need both of these, which would lead to ambiguous instance heads:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        zapWith = zapWithAdjunctionFG
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        zapWith = zapWithAdjunctionGF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Furthermore, we can also define a third instance of &lt;code&gt;Zap&lt;/code&gt; over composition, which doesn't even care about &lt;code&gt;Adjunction&lt;/code&gt;, which also conflicts with the above:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Zap&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    zapWith f a b =
        zapWith (zapWith f) (decompose a) (decompose b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could use the standard Haskell trick of making different compositions based on which instance of &lt;code&gt;Zap&lt;/code&gt; you want to support, but the combinatorial explosion of constructors here when combined with the other reasons you may want to compose a pair of functors leads to a bit of absurdity, especially since I'm using it to capture a relationship no one cares about.&lt;/p&gt;
&lt;p&gt;Consequently, &lt;a href=&quot;https://comonad.com/haskell/category-extras/&quot;&gt;category-extras&lt;/a&gt; does not capture this constraint.&lt;/p&gt;
&lt;h2 id=&quot;cozapping&quot;&gt;Cozapping&lt;/h2&gt;
&lt;p&gt;As a final aside, we noted previously that &lt;code&gt;Traversable&lt;/code&gt; functors were costrong. If a strong &lt;code&gt;Adjunction&lt;/code&gt; gives rise to a couple of instances of &lt;code&gt;Zap&lt;/code&gt;, we'd expect a similar relationship between a notion of &lt;code&gt;Cozap&lt;/code&gt; and a costrong &lt;code&gt;Adjunction&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what would cozapping be?&lt;/p&gt;
&lt;p&gt;First lets take a step back and break down zipWith into a couple of steps. If we note that &lt;code&gt;zapWith (,)&lt;/code&gt; looks like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;prezapAdjunctionGF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; g f =&amp;gt; f a -&amp;gt; g b -&amp;gt; (a,b)
&lt;span class=&quot;hljs-title&quot;&gt;prezapAdjunctionGF&lt;/span&gt; a b =
    swap . counit . fmap (uncurry strength . swap) $ strength a b
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; swap ~(a,b) = (b,a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whereupon we can run the output through the canonical eval morphism for exponentials in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; :: (a -&amp;gt; b, a) -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;eval&lt;/span&gt; (f,a) = f a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can run everything backwards (modulo the noise caused by currying) in the first definition above and get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;precozapAdjunctionFG&lt;/span&gt; ::
    (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; g) =&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (f a) (g b)
&lt;span class=&quot;hljs-title&quot;&gt;precozapAdjunctionFG&lt;/span&gt; =
    costrength . fmap (swap . costrength) . unit . swap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, we lack a &lt;code&gt;coeval&lt;/code&gt; morphism for &lt;a href=&quot;http://citeseer.ist.psu.edu/filinski89declarative.html&quot;&gt;coexponentials&lt;/a&gt;, since &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; lacks coexponentials -- with good reason! If &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Hask}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Hask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; was a co-CCC then it would degenerate to a rather boring poset.&lt;/p&gt;
&lt;p&gt;But that said, even getting this far, how many adjunctions are there between &lt;code&gt;Traversable&lt;/code&gt; functors in Haskell, really?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/zapping-strong-adjunctions/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Linear Bloom Filters</title><link>https://comonad.com/reader/2008/linear-bloom-filters/</link><guid isPermaLink="false">https://comonad.com/reader/2008/linear-bloom-filters/</guid><pubDate>Tue, 03 Jun 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 3 June 2008&lt;/p&gt;&lt;span id=&quot;more-66&quot;&gt;&lt;/span&gt;&lt;p&gt;This post is a bit of a departure from my recent norm. It contains no category theory whatsoever. None. I promise.&lt;/p&gt;
&lt;p&gt;Now that I've bored away the math folks, I'll point out that this also isn't a guide to better horticulture. Great, there goes the rest of you.&lt;/p&gt;
&lt;p&gt;Instead, I want to talk about &lt;a href=&quot;http://citeseer.ist.psu.edu/bloom70spacetime.html&quot;&gt;Bloom filters&lt;/a&gt;, Bloom joins for distributed databases and some novel extensions to them that let you trade in resources that we have in abundance for ones that are scarce, which I've been using for the last few months and which I have never before seen before in print. Primarily because I guess they have little to do with the strengths of Bloom filters.&lt;/p&gt;
&lt;p&gt;For practical purposes you will need to use a &lt;a href=&quot;http://en.wikipedia.org/wiki/Bloom_filter#Counting_filters&quot;&gt;counted&lt;/a&gt; or &lt;a href=&quot;http://theory.stanford.edu/~matias/papers/sbf-sigmod-03.pdf&quot;&gt;spectral&lt;/a&gt; Bloom filter for the purposes of the structure mentioned below. However, as these introduce nothing novel, and simply muddle the exposition, I'll ignore counting and spectral Blooms for now.&lt;/p&gt;
&lt;h2 id=&quot;bloom-filters&quot;&gt;Bloom Filters&lt;/h2&gt;
&lt;p&gt;Ok, so what is a Bloom filter? Bloom filters date back to 1970. A simple Bloom filter is a novel data structure for approximating membership in a set, yielding only false positives. A filter consists of an m-bit array and k distinct hash functions. To add an element to the filter you run it through each of the k hash functions and setting the appropriate bits. A value is considered to be a member of the set if you hash it through each of the k functions and each of the target bits is set. It is easy to see that this can only result in a false positive, but its also easy to see that you need to set the size of the array before you start adding elements to it, and that you need to balance the number of hash functions to the overall desired precision of your filter. In general you want to have about half of the bits set in the resulting array to maximize your information density -- a fact which can be derived with elementary calculus. From which you can figure out that you get optimal results when &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mfrac&gt;&lt;mi&gt;ln&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;k = \frac{m}{n} \ln 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0404em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6954em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;ln&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We can readily approximate k distinct hashing functions by using a single one-way hashing function and carving it up into a number of hashing functions that consist of the right number of bits each. A simpler approach due to &lt;a href=&quot;http://www.eecs.harvard.edu/~kirsch/pubs/bbbf/esa06.pdf&quot;&gt;Kirsch and Mitzenmacher&lt;/a&gt; is to sacrifice the independence of the hash functions without particularly adversely affecting the properties of the filter.&lt;/p&gt;
&lt;p&gt;The nice thing about a Bloom filter is that the parameters m and k can be varied to tune space requirements and precision.&lt;/p&gt;
&lt;h2 id=&quot;improving-locality&quot;&gt;Improving Locality&lt;/h2&gt;
&lt;p&gt;One common way to improve the locality of reference for excessively large Bloom filters is to break up the structure into two tiers. You have an upper tier in which you use a single hash function to bin the data, then within the bin you placed the data you run the remaining k-1 hash functions. This can result in a 'lumpier' distribution of data, but generally improves performance because if you exceed working memory, this model can typically page in a single page from disk to handle the k-1 writes. When you figure that it is common to use between several hashing functions with a bloom filter this can result in a several-fold performance improvement as the data set grows and you become IO bound. As a result of being primarily to optimize IO you typically want to have a bin size that corresponds with your block or page size.&lt;/p&gt;
&lt;p&gt;As an admittedly &lt;em&gt;completely&lt;/em&gt; unintelligible aside, I am particularly fond of 8k bins for a simple Bloom filter, because they nicely consume 16 bits of hash evenly, and 4k bins, when used with 4 bit counting Blooms, page in and out efficiently and compress nicely with an arithmetic/exponentiated Huffman encoding into near even multiples of the ethernet packet MTU when you tune the ratio of set bits carefully, I've found this to be beneficial for tweaking real world performance.&lt;/p&gt;
&lt;h2 id=&quot;bloom-joins&quot;&gt;Bloom Joins&lt;/h2&gt;
&lt;p&gt;Given a pair of bloom filters that share a given size m and which use the same k hash functions. You can take their intersection (or union) quite efficiently with bitwise and (or or). This is a well known technique for dealing with distributed database joins when you have data distributed across multiple servers joining against data distributed across other servers. In general, you are only interested in transmitting the data that exists on both sides of the join.&lt;/p&gt;
&lt;p&gt;(You can technically free yourself from the requirement that both sides agree on the number of hash functions if you are willing to accept more false positives and you test for membership in the result set using just the hash functions contained in both Blooms. The easiest way to do this is to just agree on an order in which hash functions will be used, which comes for free from the Kirsch/Mitzenmacher approach mentioned above.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The good&lt;/strong&gt;&lt;br&gt;
The nice thing about a standard Bloom join is that you can send the Bloom filter over the network quite cheaply in comparison to the data, and with the addition of counting Bloom filter tricks it can be used to calculate approximately the size of the result set. This allows you to use it to load level &lt;a href=&quot;http://labs.google.com/papers/mapreduce.html&quot;&gt;MapReduce&lt;/a&gt; style workloads effectively by estimating the size of intermediate results quite accurately before you send everything over the network to be aggregated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The bad&lt;/strong&gt;&lt;br&gt;
One problem with this model is that you have to know the size of your data set up front in order to calculate an ideal m for a desired precision level. Moreover both sides of the join have to agree on this figure m before calculating the join.&lt;/p&gt;
&lt;p&gt;Now, the main goal of a Bloom join is to conserve an scarce resource (network bandwith) by exchanging cheaper, more plentiful resources (local CPU utilization, and disk IO). In that respect it serves adequately, but we can do better if our goal is more or less purely to optimize network bandwidth. Lets carry that a bit further.&lt;/p&gt;
&lt;h2 id=&quot;linear-hash-tables&quot;&gt;Linear Hash Tables&lt;/h2&gt;
&lt;p&gt;To address the limitation that you have to know the size of the bloom a priori, we'll turn to another data structure, the &lt;a href=&quot;http://en.wikipedia.org/wiki/Linear_hash&quot;&gt;linear hash table&lt;/a&gt;. Linear hash tables were designed by Witold Litwin back in 1980 to provide an expandable hash table without a huge stairstep in the cost function whenever you hit a power of two in size. The basic idea of a linear hash table is that you grow the table gradually, by splitting one bucket at a time and using the least significant bits of your hash function.&lt;/p&gt;
&lt;p&gt;For sake of variety, I've included a C# 3.5 implementation here:&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://comonad.com/source/unavailable/asset-27.html&quot;&gt;SortedLinearHashTable.cs&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/source/unavailable/asset-28.html&quot;&gt;SinglyLinkedList.cs&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/source/unavailable/asset-29.html&quot;&gt;PreparedEqualityComparer.cs&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/source/unavailable/asset-30.html&quot;&gt;PreparedEqualityComparerTypeProxyAttribute.cs&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;For my regular audience, an implementation in Haskell using STM — incidentally was the first piece of Haskell I ever wrote — designed for read-mostly use can be found here:&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://comonad.com/haskell/thash/dist/doc/html/&quot;&gt;haddock&lt;/a&gt;]&lt;br&gt;
[&lt;a href=&quot;https://comonad.com/haskell/thash/&quot;&gt;darcs&lt;/a&gt;]&lt;/p&gt;
&lt;h2 id=&quot;a-linear-bloom-filter&quot;&gt;A Linear Bloom Filter&lt;/h2&gt;
&lt;p&gt;Now, we can look at the bi-level structure we introduced above for dealing with improved cache locality and note that we could go in a different direction and treat the upper level as a linear hash table, instead of a simple hash function! This requires that we keep not only the Bloom but also the member list (or at least their hashes). We can optimize this slightly by computing the Bloom of the member list for each page lazily. This costs us quite a bit of storage relative to a traditional Bloom filter, but we can transmit the Bloom of the resulting set over the network more cheaply than we can transmit a linear hash table and it isn't appreciably more expensive locally than a linear hash table due to only lazily constructing the Blooms.&lt;/p&gt;
&lt;p&gt;This mechanism gives rise to an actual tree of pages based on the unfolding of the linear hash table in the resulting hierarchical bloom if you choose to represent the interior of the tree.&lt;/p&gt;
&lt;p&gt;Again, this isn't a win for all scenarios, but if you are intending to transmit the resulting set over the network, and don't know its size a priori, the combination of properties from the linear hash table and the bloomed pages leads to some interesting options.&lt;/p&gt;
&lt;h2 id=&quot;linear-bloom-origami&quot;&gt;Linear Bloom Origami&lt;/h2&gt;
&lt;p&gt;Now that we have an expandable hash in our top level, we finally have the machinery to deal with how to perform a join between two linear bloom filters of different size. The model is actually quite simple. We can fold the larger bloom up by &lt;em&gt;or&lt;/em&gt;ing together the leaves that were split by the linear hash table in the larger bloom until we have the same number of pages and then perform a standard Bloom join. This frees us from the tyranny of having to have both sides of the join guess in advance a shared number of buckets to use to perform the join.&lt;/p&gt;
&lt;p&gt;As an aside, an interesting thought experiment is to go one step further and use a full-fledged sorted linear hash table for the extra cost of sorting the chains, but this doesn't seem to be useful in practice.&lt;/p&gt;
&lt;h2 id=&quot;mipmapping-blooms&quot;&gt;Mipmapping Blooms&lt;/h2&gt;
&lt;p&gt;If we are willing to pay an &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;log&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{O}(n \log n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;lo&lt;span style=&quot;margin-right:0.0139em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; cost in terms of the data set size cost in terms of CPU utilization and memory bandwidth we can gain some further performance in terms of network utilization through encoding a set of &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Mipmap&quot;&gt;mipmaps&lt;/a&gt;&quot; for our filters.&lt;/p&gt;
&lt;p&gt;Basically the idea is to fold up the tree by &lt;em&gt;or&lt;/em&gt;ing together the pages into an admissible Bloom of the dataset. Then you encode the splitting of each bit that was set in the Bloom using conditional probabilities. This can be transmitted near optimally using arithmetic encoding or exponentiated Huffman.&lt;/p&gt;
&lt;p&gt;If a bit is set in the parent Bloom, then at least one of the two bits will be set in the child Blooms; if no bit is set in the parent Bloom, then no bit can be set in the child Blooms. The probability of each bit being set in each child is for all practical intents and purposes independent and can reasonably be modeled as a function of the expected number of set bits. (This is ever-so-slightly suboptimal if the overall number of values is known). You can determine exact values for the weights of each of the three cases using conditional probabilities and then use an arithmetic compressor, or exponentiate the alphabet for a Huffman compressor — this is otherwise near worst-case for Huffman, since you have two possibilities both just shy of 50% and one much smaller probability. Nicely the regular structure of the exponentiated alphabet is very regular and can be represented efficiently. With careful choice of page size (or bit density within a page) you can transmit the initial page cheaply, and then pack multiple pages into subsequent packets.&lt;/p&gt;
&lt;p&gt;Since we can determine the relevance of portions of the tree based on partial information this may allow you to avoid transmitting some branches of the tree. More interestingly we can use it to figure out approximately the size of the join set from the first few pages transmitted and to gain gradual refinements as both sides of the join supply more information.&lt;/p&gt;
&lt;p&gt;If you wanted to optimize strictly for network bandwidth and were willing to accept additional latency you could prune branches of the tree after it was clear that the intersection was empty and so no further resolution was required, but in my experience this optimization doesn't seem to be worth the effort.&lt;/p&gt;
&lt;h2 id=&quot;incremental-update&quot;&gt;Incremental Update&lt;/h2&gt;
&lt;p&gt;Interestingly if you have already shared a Linear Bloom and need to update your copy it admits a cheap network representation using the same arithmetic/exponentiated Huffman encoding trick mentioned earlier. You lose the ability to ignore all unset bits in the dataset because extending the set of known values will in all likelihood set new bits, but as you add members you can transmit splits using the same mechanism used above, and you have the actual member set needed to populate the child pages accurately.&lt;/p&gt;
&lt;p&gt;Interestingly it is the ability to mipmap the intermediate results that sometimes makes it worth dealing with a suboptimal choice of density for the overall Bloom filter, because it only affects the cost on either end of the network, it doesn't affect the network transmission costs all that adversely and more sparse population early in the tree can allow you to have a less oversaturated tree near the root, allowing earlier pruning of branches - I have yet to take this from an art to a science.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I had intended to explain things in more detail and delve into the asymptotic behavior of hierarchical and linear Blooms, but various people have been hammering me to just post this already, so here it is.&lt;/p&gt;
&lt;p&gt;So to recap, we took a normal (or counted or spectral) Bloom filter, crossbred it with Litwin's linear hash table and found that the mutant offspring is an approximation of a set that is better suited to sharing over the network than either structure alone, with a memory usage profile similar to that of a linear hash table. Interestingly as a side effect you can go one step further and allow for transmission of a requested subset of the exact hashes present in which case we've really only used the Blooms to provide partial information about the underlying linear hash table, which can aid in the subsequent join process.&lt;/p&gt;
&lt;p&gt;And yes, they are probably better named something like Bloomed linear hash tables, but that doesn't roll off the tongue.&lt;/p&gt;
&lt;p&gt;If there is enough interest and I don't get dragged into other things, I might see about packaging up and genericizing some code that I had lying around intended for production use into a more general purpose library for Linear Bloom Filters.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/linear-bloom-filters/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Kan Extensions III: As Ends and Coends</title><link>https://comonad.com/reader/2008/kan-extension-iii/</link><guid isPermaLink="false">https://comonad.com/reader/2008/kan-extension-iii/</guid><pubDate>Mon, 26 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 May 2008&lt;/p&gt;&lt;span id=&quot;more-65&quot;&gt;&lt;/span&gt;&lt;p&gt;Grant B. &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/#comment-1412&quot;&gt;asked me&lt;/a&gt; to post the derivation for the right and left Kan extension formula used in previous Kan Extension posts (&lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/&quot;&gt;1&lt;/a&gt;,&lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;2&lt;/a&gt;). For that we can turn to the definition of Kan extensions in terms of ends, but first we need to take a couple of steps back to find a way to represent (co)ends in Haskell.&lt;/p&gt;
&lt;h2 id=&quot;dinatural-transformations&quot;&gt;Dinatural Transformations&lt;/h2&gt;
&lt;p&gt;Rather than repeat the &lt;a href=&quot;http://en.wikipedia.org/wiki/Dinatural_transformation&quot;&gt;definition&lt;/a&gt; here, we'll just note we can define a dinatural transformation in Haskell letting polymorphism represent the family of morphisms.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dinatural&lt;/span&gt; f g = forall a. f a a -&amp;gt; g a a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;ends&quot;&gt;Ends&lt;/h2&gt;
&lt;p&gt;So what is an end?&lt;/p&gt;
&lt;p&gt;An end is a universal dinatural transformation from some object e to some functor s.&lt;/p&gt;
&lt;p&gt;Diving into the formal definition:&lt;/p&gt;
&lt;p&gt;Given a functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msup&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathcal{C}^{op} \times \mathcal{C} \to \mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and end of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is a pair &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(e,\omega)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;ω&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; where &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;e&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is an object of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and omega is a dinatural transformation from e to S such that given any other dinatural transformation &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\beta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0528em;&quot;&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to S from another object x in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, there exists a unique morphism &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;h : x \to e&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, such that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;β&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\beta_a = \omega_a \cdot h&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0528em;&quot;&gt;β&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.5945em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;ω&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; for every &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We usually choose to write ends as &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mo&gt;∫&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;e = \int_c S(c,c)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.1608em;vertical-align:-0.3558em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;margin-right:0.1945em;position:relative;top:-0.0006em;&quot;&gt;∫&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:-0.0544em;&quot;&gt;&lt;span style=&quot;top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3558em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and abuse terminology calling &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;e&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; the end of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Note this uses a dinatural transformation from an object &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which we can choose to represent an arbitrary dinatural transformation from an object &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to a functor &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in terms of a dinatural transformation from the constant bifunctor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x a b = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runConst&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This leaves us with the definition of a dinatural transformation from an object as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Dinatural&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x) s ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; x a a -&amp;gt; s a a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but the universal quantification over the &lt;code&gt;Const&lt;/code&gt; term is rather useless and the &lt;code&gt;Const&lt;/code&gt; bifunctor is supplying no information so we can just specialize that down to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DinaturalFromObject&lt;/span&gt; x s = x -&amp;gt; forall a. s a a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, clearly for any such transformation, we could rewrite it trivially using the definition:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; s = forall a. s a a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\omega&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;ω&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; = id.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DinaturalFromObject&lt;/span&gt; x s = x -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And so &lt;code&gt;End&lt;/code&gt; above fully complies with the definition for an end, and we just say &lt;code&gt;e = End s&lt;/code&gt; abusing the terminology as earlier. The function &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\omega&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;ω&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; = id is implicit.&lt;/p&gt;
&lt;p&gt;For End to be a proper end, we assume that &lt;code&gt;s&lt;/code&gt; is contravariant in its first argument and covariant in its second argument.&lt;/p&gt;
&lt;h2 id=&quot;example-hom&quot;&gt;Example: Hom&lt;/h2&gt;
&lt;p&gt;A good example of this is (-&amp;gt;) in Haskell, which is as category theory types would call it the Hom functor for Hask. Then &lt;code&gt;End (-&amp;gt;) = forall a. a -&amp;gt; a&lt;/code&gt; which has just one inhabitant &lt;code&gt;id&lt;/code&gt; if you discard cheating inhabitants involving fix or undefined.&lt;/p&gt;
&lt;p&gt;We write &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C}(a,b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{Hom}_\mathcal{C}(a,b)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Hom&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to denote &lt;code&gt;a -&amp;gt; b&lt;/code&gt;. Similarly we use &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b^a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to denote an exponential object within a category, and since in Haskell we have first class functions using the same syntax this also translates to &lt;code&gt;a -&amp;gt; b&lt;/code&gt;. We'll need these later.&lt;/p&gt;
&lt;h2 id=&quot;example-natural-transformations&quot;&gt;Example: Natural Transformations&lt;/h2&gt;
&lt;p&gt;If we define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;HomFG&lt;/span&gt; f g a b =&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;HomFG&lt;/span&gt; { runHomFG :: f a -&amp;gt; g b }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then we &lt;em&gt;could&lt;/em&gt; of course choose to define natural transformations in terms of &lt;code&gt;End&lt;/code&gt; as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; f g = &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;HomFG&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- forall a. f a -&amp;gt; g a&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;right-kan-extension-as-an-end&quot;&gt;Right Kan Extension as an End&lt;/h2&gt;
&lt;p&gt;Turning to &lt;a href=&quot;http://en.wikipedia.org/wiki/Kan_extension#Kan_extensions_as_coends&quot;&gt;Wikipedia&lt;/a&gt; or Categories for the Working Mathematician you can find the following definition for right Kan extension of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; along &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;K&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in terms of ends.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;R&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mo&gt;∫&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(\mathrm{Ran}_KT)c=\int_m Tm^{\mathbf{C}(c,Km)}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2438em;vertical-align:-0.3558em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;margin-right:0.1945em;position:relative;top:-0.0006em;&quot;&gt;∫&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:-0.0544em;&quot;&gt;&lt;span style=&quot;top:-2.3442em;margin-left:-0.1945em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3558em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.888em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Working by rote, we note that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{C}(c,Km)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbf&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is just &lt;code&gt;c -&amp;gt; K m&lt;/code&gt; as noted above, and that &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(Tm)^{\mathbf{C}(c,Km)}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.138em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.888em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathbf mtight&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is then just &lt;code&gt;(c -&amp;gt; K m) -&amp;gt; T m'&lt;/code&gt;. So now we just have to take the end over that, and read off:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;RanT&lt;/span&gt; k t c m m' = (&lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) -&amp;gt; t m'&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; k t c = &lt;span class=&quot;hljs-type&quot;&gt;End&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;RanT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which, modulo newtype noise is the same as the type previously supplied type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; f g c = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runRan&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;coends&quot;&gt;Coends&lt;/h2&gt;
&lt;p&gt;The derivation for the left Kan extension follows similarly from defining &lt;a href=&quot;http://en.wikipedia.org/wiki/Coend_%28category_theory%29#Coend&quot;&gt;coends&lt;/a&gt; over &lt;strong&gt;Hask&lt;/strong&gt; in terms of existential quantification and copowers as products.&lt;/p&gt;
&lt;p&gt;The coend derivation is complicated slightly by Haskell's semantics. Disposing of the constant bifunctor as before we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DinaturalToObject&lt;/span&gt; s c = forall a. (&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which since we want to be able to box up the s a a term separately, we need to use existential quantification.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. s a a -&amp;gt; c) ~ (exists a. s a a) -&amp;gt; c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We cannot represent this directly in terms of a type annotation in Haskell, but we can do so with a data type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Coend&lt;/span&gt; f = forall a. &lt;span class=&quot;hljs-type&quot;&gt;Coend&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Recall that in Haskell, existential quantification is represented by using universal quantification outside of the type constructor.&lt;/p&gt;
&lt;p&gt;The main difference is that in our coend &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;ζ&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(e,\zeta)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0738em;&quot;&gt;ζ&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; the function &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ζ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\zeta&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0738em;&quot;&gt;ζ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is now &lt;code&gt;runCoend&lt;/code&gt; instead of &lt;code&gt;id&lt;/code&gt;, because we have a &lt;code&gt;Coend&lt;/code&gt; data constructor around the existential. Technicalities make it a little more complicated than that even, because you can't define a well-typed &lt;code&gt;runCoend&lt;/code&gt; and have to use pattern matching on the &lt;code&gt;Coend&lt;/code&gt; data constructor to avoid having an existentially quantified type escape the current scope, but the idea is the same.&lt;/p&gt;
&lt;h2 id=&quot;left-kan-extension-as-a-coend&quot;&gt;Left Kan Extension as a Coend&lt;/h2&gt;
&lt;p&gt;Then given the definition for the left Kan extension of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; along &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;K&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; as a coend:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;L&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msup&gt;&lt;mo&gt;∫&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msup&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(\mathrm{Lan}_KT)c=\int^m \mathbf{C}(Km,c)\cdot Tm&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Lan&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.1654em;vertical-align:-0.3061em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;margin-right:0.1945em;position:relative;top:-0.0006em;&quot;&gt;∫&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8593em;&quot;&gt;&lt;span style=&quot;top:-3.2579em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbf&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⋅&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;we can read off:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;LanT&lt;/span&gt; k t c m m' = &lt;span class=&quot;hljs-type&quot;&gt;LanT&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m'&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; k t c = &lt;span class=&quot;hljs-type&quot;&gt;Coend&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;LanT&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which is &lt;em&gt;almost&lt;/em&gt; isomorphic to the previously supplied type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; k t c = forall m. &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;except for the fact that we had to use two layers of data declarations when using the separate &lt;code&gt;Coend&lt;/code&gt; data type, so we introduced an extra place for a &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;⊥&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\perp&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊥&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; to hide.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;newtype&lt;/code&gt; isn't allowed to use existential quantification in Haskell, so this form forces a spurious case analysis that we'd prefer to do without. This motivates why &lt;a href=&quot;https://hackage.haskell.org/package/category-extras&quot;&gt;category-extras&lt;/a&gt; uses a separate definition for &lt;code&gt;Lan&lt;/code&gt; rather than the more elaborate definition in terms of &lt;code&gt;Coend&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;[Edit: Fixed a typo in the definition of RanT]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/kan-extension-iii/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Kan Extensions II: Adjunctions, Composition, Lifting</title><link>https://comonad.com/reader/2008/kan-extensions-ii/</link><guid isPermaLink="false">https://comonad.com/reader/2008/kan-extensions-ii/</guid><pubDate>Thu, 22 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 22 May 2008&lt;/p&gt;&lt;span id=&quot;more-64&quot;&gt;&lt;/span&gt;&lt;p&gt;I want to spend some more time talking about Kan extensions, composition of Kan extensions, and the relationship between a monad and the monad generated by a monad.&lt;/p&gt;
&lt;p&gt;But first, I want to take a moment to recall adjunctions and show how they relate to some standard (co)monads, before tying them back to &lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/&quot;&gt;Kan extensions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;adjunctions-101&quot;&gt;Adjunctions 101&lt;/h2&gt;
&lt;p&gt;An adjunction between categories &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; consists of a pair of functors &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F : \mathcal{C} \to \mathcal{D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G : \mathcal{D} \to \mathcal{C}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathcal&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and a natural isomorphism:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;H&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;m&lt;/mi&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi : \mathrm{Hom}_\mathcal{D} (F-, =) \to \mathrm{Hom}_\mathcal{C} (-, G=)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Hom&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Hom&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We call &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; the left adjoint functor, and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; the right adjoint functor and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(F,G)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; an adjoint pair, and write this relationship as &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F \dashv G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Borrowing a Haskell definition from Dave Menendez, an adjunction from the category of Haskell types (&lt;strong&gt;Hask&lt;/strong&gt;) to &lt;strong&gt;Hask&lt;/strong&gt; given by a pair of Haskell &lt;code&gt;Functor&lt;/code&gt; instances can be defined as follows, where phi is witnessed by &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; = &lt;code&gt;leftAdjunct&lt;/code&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;ϕ&lt;/mi&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\phi^{-1}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0085em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ϕ&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; = &lt;code&gt;rightAdjunct&lt;/code&gt;. [&lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Adjunction.html&quot;&gt;haddock&lt;/a&gt;]&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    unit   :: a -&amp;gt; g (f a)
    counit :: f (g a) -&amp;gt; a
    leftAdjunct  :: (f a -&amp;gt; b) -&amp;gt; a -&amp;gt; g b
    rightAdjunct :: (a -&amp;gt; g b) -&amp;gt; f a -&amp;gt; b

    unit = leftAdjunct id
    counit = rightAdjunct id
    leftAdjunct f = fmap f . unit
    rightAdjunct f = counit . fmap f
&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;category-diagram&quot; id=&quot;adjunction&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/figures/adjunction.svg&quot; alt=&quot;F from C to D is left adjoint to G from D to C.&quot;&gt;&lt;figcaption&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is left adjoint to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, with unit &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi mathvariant=&quot;script&quot;&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta : 1_{\mathcal C} \Rightarrow GF&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;η&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0583em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;GF&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and counit &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ε&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi mathvariant=&quot;script&quot;&gt;D&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\varepsilon : FG \Rightarrow 1_{\mathcal D}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ε&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathcal mtight&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;currying-and-uncurrying&quot;&gt;Currying and Uncurrying&lt;/h2&gt;
&lt;p&gt;The most well known adjunction to a Haskell programmer is between the functors given by &lt;code&gt;((,)e)&lt;/code&gt; and &lt;code&gt;((-&amp;gt;)e)&lt;/code&gt;. (Recall that you can read &lt;code&gt;((,)e)&lt;/code&gt; as &lt;code&gt;(e,)&lt;/code&gt; and &lt;code&gt;((-&amp;gt;)e)&lt;/code&gt; as &lt;code&gt;(e-&amp;gt;)&lt;/code&gt;; however, the latter syntax isn't valid Haskell as you aren't allowed to make &lt;code&gt;(,)&lt;/code&gt; and &lt;code&gt;(-&amp;gt;)&lt;/code&gt; sections. We use this adjunction most every day in the form of the functions &lt;code&gt;curry&lt;/code&gt; and &lt;code&gt;uncurry&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;curry&lt;/span&gt; :: ((a, b) -&amp;gt; c) -&amp;gt; a -&amp;gt; b -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;curry&lt;/span&gt; f x y = f (x,y)

&lt;span class=&quot;hljs-title&quot;&gt;uncurry&lt;/span&gt; :: (a -&amp;gt; b -&amp;gt; c) -&amp;gt; (a, b) -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;uncurry&lt;/span&gt; f ~(x,y) = f x y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However the arguments are unfortunately slightly flipped around when we go to define this as an adjunction.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; ((,)e) ((-&amp;gt;)e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  leftAdjunct f a e  = f (e,a)
  rightAdjunct f ~(e,a) = f a e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This adjunction defines the relationship between the anonymous &lt;a href=&quot;http://www.haskell.org/all_about_monads/html/readermonad.html&quot;&gt;reader monad&lt;/a&gt; and the anonymous &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad-Reader.html&quot;&gt;reader comonad&lt;/a&gt; (aka the product comonad).&lt;/p&gt;
&lt;h2 id=&quot;all-readers-are-the-same&quot;&gt;All Readers are the Same&lt;/h2&gt;
&lt;p&gt;As an aside, if you look at the reader arrow, reader monad and reader comonad all side by side you can see that they are all basically the same thing. Kleisli arrows for the anonymous reader monad have the form &lt;code&gt;a -&amp;gt; e -&amp;gt; b&lt;/code&gt;. The Reader arrow takes the form &lt;code&gt;arr (a, e) b&lt;/code&gt;, which when &lt;code&gt;arr&lt;/code&gt; is &lt;code&gt;(-&amp;gt;)&lt;/code&gt; this reads as &lt;code&gt;(a,e) -&amp;gt; b&lt;/code&gt;, which is just a curried Kleisli arrow for the Reader monad. On the other hand the reader comonad is &lt;code&gt;((,)e)&lt;/code&gt;, and its CoKleisli arrows have the form &lt;code&gt;(e,a) -&amp;gt; b&lt;/code&gt;. So, putting these side by side:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; e -&amp;gt; b
(a , e) -&amp;gt; b
(e , a) -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can clearly see these are all the same thing!&lt;/p&gt;
&lt;h2 id=&quot;state-and-composing-adjunctions&quot;&gt;State and Composing Adjunctions&lt;/h2&gt;
&lt;p&gt;Once we define functor composition:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt; f g a = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;decompose&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap (fmap f) . decompose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that every adjunction gives rise to a monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . unit
  m &amp;gt;&amp;gt;= f =
    &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap (rightAdjunct (decompose . f)) $ decompose m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and if you happen to have a &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad.html&quot;&gt;Comonad typeclass&lt;/a&gt; lying around, a comonad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract :: w a -&amp;gt; a
  duplicate :: w a -&amp;gt; w (w a)
  extend :: (w a -&amp;gt; b) -&amp;gt; w a -&amp;gt; w b
  extend f = fmap f . duplicate
  duplicate = extend id
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract = counit . decompose
  extend f =
    &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap (leftAdjunct (f . &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt;)) . decompose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In reality, adjunction composition is of course not the only way you could form a monad by composition, so in practice a single composition constructor leads to ambiguity. Hence why in category-extras there is a base &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Composition.html&quot;&gt;&lt;code&gt;CompF&lt;/code&gt;&lt;/a&gt; functor, and &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Adjunction.html#t%3AACompF&quot;&gt;specialized variations&lt;/a&gt; for different desired instances. For simplicity, I'll stick to &lt;code&gt;`O`&lt;/code&gt; here.&lt;/p&gt;
&lt;p&gt;We can compose adjunctions, yielding an adjunction, so long as we are careful to place things in the right order:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f2&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;f1&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g1&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g2&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    counit =
      counit . fmap (counit . fmap decompose) . decompose
    unit =
      &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap (fmap &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . unit) . unit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact, if we use the adjunction defined above, we can see that its just the &lt;code&gt;State&lt;/code&gt; monad!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; e ((-&amp;gt;)e `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` (,)e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  get = compose $ \s -&amp;gt; (s,s)
  put s = compose $ const (s,())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not that I'd be prone to consider using that representation, but we can also see that we get the &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad-Context.html&quot;&gt;context comonad&lt;/a&gt; this way:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;ComonadContext&lt;/span&gt; s w | w -&amp;gt; s &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    getC :: w a -&amp;gt; s
    modifyC :: (s -&amp;gt; s) -&amp;gt; w a -&amp;gt; a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadContext&lt;/span&gt; e ((,)e `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` (-&amp;gt;)e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  getC = fst . decompose
  modifyC f = uncurry (flip id . f) . decompose
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;adjunctions-as-kan-extensions&quot;&gt;Adjunctions as Kan Extensions&lt;/h2&gt;
&lt;p&gt;Unsurprisingly, since pretty much all of category theory comes around to being an observation about Kan extensions in the end, we can find some laws relating left- and right- Kan extensions to adjunctions.&lt;/p&gt;
&lt;p&gt;Recall the definitions for right and left Kan extensions over &lt;strong&gt;Hask&lt;/strong&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h a = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;
  { runRan :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. (a -&amp;gt; g b) -&amp;gt; h b }
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h a = forall b. &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Formally, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mo&gt;⊣&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F \dashv G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊣&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; if and only if the right Kan extension &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;R&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msub&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{Ran}_G 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; exists and is preserved by &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. (Saunders Mac Lane, Categories for the Working Mathematician p248). We can use this in Haskell to define a &lt;a href=&quot;http://en.wikipedia.org/wiki/Natural_transformation&quot;&gt;natural isomorphism&lt;/a&gt; between &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;Ran g Identity&lt;/code&gt; witnessed by &lt;code&gt;adjointToRan&lt;/code&gt; and &lt;code&gt;ranToAdjoint&lt;/code&gt; below:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;adjointToRan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;adjointToRan&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; $ rightAdjunct a f)

&lt;span class=&quot;hljs-title&quot;&gt;ranToAdjoint&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;ranToAdjoint&lt;/span&gt; r = runIdentity (runRan r unit)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can construct a similar natural isomorphism for the right adjoint &lt;code&gt;g&lt;/code&gt; of a &lt;code&gt;Functor&lt;/code&gt; &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;Lan f Identity&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;adjointToLan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; g a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;adjointToLan&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; counit . &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;lanToAdjoint&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a -&amp;gt; g a
&lt;span class=&quot;hljs-title&quot;&gt;lanToAdjoint&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f v) = leftAdjunct f (runIdentity v)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, with that in hand we can see that &lt;code&gt;Ran f Identity -| f -| Lan f Identity&lt;/code&gt;, presuming &lt;code&gt;Ran f Identity&lt;/code&gt; and &lt;code&gt;Lan f Identity&lt;/code&gt; exist.&lt;/p&gt;
&lt;h2 id=&quot;a-more-general-connection&quot;&gt;A More General Connection&lt;/h2&gt;
&lt;p&gt;Now, the first isomorphism above can be seen as a special case of a more general law relating functor composition and Kan extensions, where &lt;code&gt;h = Identity&lt;/code&gt; in the composition below:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ranToComposedAdjoint&lt;/span&gt;
  :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g
  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h a -&amp;gt; (h `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` f) a
&lt;span class=&quot;hljs-title&quot;&gt;ranToComposedAdjoint&lt;/span&gt; r = &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (runRan r unit)

&lt;span class=&quot;hljs-title&quot;&gt;composedAdjointToRan&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; h, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g)
  =&amp;gt; (h `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` f) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h a
&lt;span class=&quot;hljs-title&quot;&gt;composedAdjointToRan&lt;/span&gt; f =
  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\a -&amp;gt; fmap (rightAdjunct a) (decompose f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, we get the more general relationship for &lt;code&gt;Lan&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lanToComposedAdjoint&lt;/span&gt;
  :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; h, &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g)
  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f h a -&amp;gt; (h `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) a
&lt;span class=&quot;hljs-title&quot;&gt;lanToComposedAdjoint&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f v) =
  &lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; (fmap (leftAdjunct f) v)

&lt;span class=&quot;hljs-title&quot;&gt;composedAdjointToLan&lt;/span&gt;
  :: &lt;span class=&quot;hljs-type&quot;&gt;Adjunction&lt;/span&gt; f g
  =&amp;gt; (h `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f h a
&lt;span class=&quot;hljs-title&quot;&gt;composedAdjointToLan&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; counit . decompose
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;composing-kan-extensions&quot;&gt;Composing Kan Extensions&lt;/h2&gt;
&lt;p&gt;Using the above with the laws for composing right Kan extensions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;composeRan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (f `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) h a
&lt;span class=&quot;hljs-title&quot;&gt;composeRan&lt;/span&gt; r =
  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\f -&amp;gt; runRan (runRan r (decompose . f)) id)

&lt;span class=&quot;hljs-title&quot;&gt;decomposeRan&lt;/span&gt;
  :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f
  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (f `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) h a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h) a
&lt;span class=&quot;hljs-title&quot;&gt;decomposeRan&lt;/span&gt; r =
  &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\f -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\g -&amp;gt; runRan r (&lt;span class=&quot;hljs-type&quot;&gt;Compose&lt;/span&gt; . fmap g . f)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or the laws for composing left Kan extensions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;composeLan&lt;/span&gt;
  :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f
  =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h) a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (f `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) h a
&lt;span class=&quot;hljs-title&quot;&gt;composeLan&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h)) =
  &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (f . fmap g . decompose) h

&lt;span class=&quot;hljs-title&quot;&gt;decomposeLan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (f `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` g) h a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h) a
&lt;span class=&quot;hljs-title&quot;&gt;decomposeLan&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f h) = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (f . compose) (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; id h)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;can give you a lot of ways to construct monads:&lt;/p&gt;
&lt;h2 id=&quot;right-kan-extension-as-almost-a-monad-transformer&quot;&gt;Right Kan Extension as (almost) a Monad Transformer&lt;/h2&gt;
&lt;p&gt;You can lift many of operations from a monad m to the codensity monad of &lt;code&gt;m&lt;/code&gt;. Unfortunately, we don't have quite the right type signature for an instance of &lt;code&gt;MonadTrans&lt;/code&gt;, so we'll have to make do with our own methods:&lt;/p&gt;
&lt;p&gt;[Edit: this has been since factored out into &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Monad-Codensity.html&quot;&gt;Control.Monad.Codensity&lt;/a&gt; to allow &lt;code&gt;Codensity&lt;/code&gt; to actually be an instance of &lt;code&gt;MonadTrans&lt;/code&gt;]&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;liftRan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; m a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; m m a
&lt;span class=&quot;hljs-title&quot;&gt;liftRan&lt;/span&gt; m = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (m &amp;gt;&amp;gt;=)

&lt;span class=&quot;hljs-title&quot;&gt;lowerRan&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; m m a -&amp;gt; m a
&lt;span class=&quot;hljs-title&quot;&gt;lowerRan&lt;/span&gt; a = runRan a return
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; r m =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;MonadReader&lt;/span&gt; r (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    ask = liftRan ask
    local f m = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\c -&amp;gt; ask &amp;gt;&amp;gt;=
        \r -&amp;gt; local f (runRan m (local (const r) . c)))
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    liftIO = liftRan . liftIO
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; s m =&amp;gt;
  &lt;span class=&quot;hljs-type&quot;&gt;MonadState&lt;/span&gt; s (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    get = liftRan get
    put = liftRan . put
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact the list of things you can lift is pretty much the same as what you can lift over the &lt;code&gt;ContT&lt;/code&gt; monad transformer due to the similarity in the types. However, just because you lifted the operation into the right or left Kan extension, doesn't mean that it has the same asymptotic performance.&lt;/p&gt;
&lt;p&gt;Similarly we can lift many comonadic operations to the &lt;code&gt;Density&lt;/code&gt; comonad of a comonad using &lt;code&gt;Lan&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;[Edit: Refactored out into &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad-Density.html&quot;&gt;Control.Comonad.Density&lt;/a&gt;]&lt;/p&gt;
&lt;h2 id=&quot;changing-representation&quot;&gt;Changing Representation&lt;/h2&gt;
&lt;p&gt;Given a &lt;code&gt;f -| g&lt;/code&gt;, &lt;code&gt;g `O` f&lt;/code&gt; is a monad, and &lt;code&gt;Ran (g `O` f) (g `O` f)&lt;/code&gt; is the monad generated by &lt;code&gt;(g `O` f)&lt;/code&gt;, described in the previous post. We showed above that this monad can do many of the same things that the original monad could do. From there you can &lt;code&gt;decomposeRan&lt;/code&gt; to get &lt;code&gt;Ran g (Ran f (g `O` f))&lt;/code&gt;, which you can show to be yet another monad, and you can continue on from there.&lt;/p&gt;
&lt;p&gt;Each of these monads may have different operational characteristics and performance tradeoffs. For instance the codensity monad of a monad can offer &lt;a href=&quot;http://wwwtcs.inf.tu-dresden.de/~voigt/mpc08.pdf&quot;&gt;better asymptotic performance&lt;/a&gt; in some usage scenarios.&lt;/p&gt;
&lt;p&gt;Similarly the left Kan extension can be used to manipulate the representation of a comonad.&lt;/p&gt;
&lt;p&gt;All of this code is encapsulated in &lt;a href=&quot;https://hackage.haskell.org/package/category-extras&quot;&gt;category-extras&lt;/a&gt; [&lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/&quot;&gt;docs&lt;/a&gt;] [&lt;a href=&quot;https://comonad.com/haskell/category-extras/&quot;&gt;darcs&lt;/a&gt;] as of release 0.51.0&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions-ii/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Kan Extensions</title><link>https://comonad.com/reader/2008/kan-extensions/</link><guid isPermaLink="false">https://comonad.com/reader/2008/kan-extensions/</guid><pubDate>Tue, 20 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 20 May 2008&lt;/p&gt;&lt;span id=&quot;more-63&quot;&gt;&lt;/span&gt;&lt;p&gt;I think I may spend a post or two talking about &lt;a href=&quot;http://en.wikipedia.org/wiki/Kan_extension&quot;&gt;Kan extensions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They appear to be black magic to Haskell programmers, but as &lt;a href=&quot;http://en.wikipedia.org/wiki/Saunders_Mac_Lane&quot;&gt;Saunders Mac Lane&lt;/a&gt; said in &lt;a href=&quot;http://www.amazon.com/Categories-Working-Mathematician-Graduate-Mathematics/dp/0387984038&quot;&gt;Categories for the Working Mathematician&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All concepts are Kan extensions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what is a Kan extension? They come in two forms: right- and left- Kan extensions.&lt;/p&gt;
&lt;p&gt;First I'll talk about right Kan extensions, since Haskell programmers have a better intuition for them.&lt;/p&gt;
&lt;h2 id=&quot;introducing-right-kan-extension&quot;&gt;Introducing Right Kan Extension&lt;/h2&gt;
&lt;p&gt;If we observe the type for a right Kan extension over the category of Haskell types:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; g h a = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;
  { runRan :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. (a -&amp;gt; g b) -&amp;gt; h b }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is defined in category-extras under &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-KanExtension.html&quot;&gt;Control.Functor.KanExtension&lt;/a&gt; along with a lot of the traditional machinery for working with them.&lt;/p&gt;
&lt;p&gt;We say that &lt;code&gt;Ran g h&lt;/code&gt; is the right Kan extension of &lt;code&gt;h&lt;/code&gt; along &lt;code&gt;g&lt;/code&gt;. and mathematicians denote it &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;R&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;bold&quot;&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbf{Ran}_G H&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8361em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathbf&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. It has a &lt;a href=&quot;http://en.wikipedia.org/wiki/Kan_extension&quot;&gt;pretty diagram&lt;/a&gt; associated with it, but thats as deep as I'll let the category theory go.&lt;/p&gt;
&lt;figure class=&quot;category-diagram&quot; id=&quot;right-kan&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://comonad.com/figures/right-kan.svg&quot; alt=&quot;G maps C to D; H maps C to E; Ran G H maps D to E, with counit from its composite with G to H.&quot;&gt;&lt;figcaption&gt;The right Kan extension, with &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;ε&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Ran&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;/mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;∘&lt;/mo&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;mo&gt;⇒&lt;/mo&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\varepsilon : (\operatorname{Ran}_G H) \circ G \Rightarrow H&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ε&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Ran&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∘&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⇒&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This looks an awful lot like the type of a continuation monad transformer:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt; r m a = &lt;span class=&quot;hljs-type&quot;&gt;ContT&lt;/span&gt;&lt;/span&gt;
  { runContT :: (a -&amp;gt; m r) -&amp;gt; m r }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The main difference is that we have two functors involved and that the body of the Kan extension is universally quantified over the value it contains, so the function it carries can't just hand you back an &lt;code&gt;m r&lt;/code&gt; it has lying around unless the functor it has closed over doesn't depend at all on the type &lt;code&gt;r&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly we can define an instance of &lt;code&gt;Functor&lt;/code&gt; for a right Kan extension without even knowing that &lt;code&gt;g&lt;/code&gt; or &lt;code&gt;h&lt;/code&gt; are functors! Anything of kind * -&amp;gt; * will do.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f m = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\k -&amp;gt; runRan m (k . f))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-monad-generated-by-a-functor&quot;&gt;The monad generated by a functor&lt;/h2&gt;
&lt;p&gt;We can take the right Kan extension of a functor &lt;code&gt;f&lt;/code&gt; along itself (this works for any functor in Haskell) and get what is known as the &lt;em&gt;monad generated by &lt;code&gt;f&lt;/code&gt;&lt;/em&gt; or the &lt;em&gt;codensity monad of &lt;code&gt;f&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return x = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\k -&amp;gt; k x)
  m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\c -&amp;gt; runRan m (\a -&amp;gt; runRan (k a) c))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This monad is mentioned in passing in &lt;a href=&quot;http://citeseer.ist.psu.edu/mccrudden02opmonoidal.html&quot;&gt;Opmonoidal Monads&lt;/a&gt; by Paddy McCrudden and dates back further to Ross Street's &quot;The formal theory of monads&quot; from 1972. The term codensity seems to date back at least to Dubuc's thesis in 1974.&lt;/p&gt;
&lt;p&gt;Again, this monad doesn't care one whit about the fact that &lt;code&gt;f&lt;/code&gt; is a Functor in the Haskell sense.&lt;/p&gt;
&lt;p&gt;This monad provides a useful opportunity for optimization. For instance Janis Voigtländer noted in &lt;a href=&quot;http://wwwtcs.inf.tu-dresden.de/~voigt/mpc08.pdf&quot;&gt;Asymptotic improvement of functions over Free Monads&lt;/a&gt; that a particular monad could be used to improve performance -- Free monads as you'll recall are the tool used in Wouter Sweirstra's &lt;a href=&quot;http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf&quot;&gt;Data Types á la Carte&lt;/a&gt;, and provide an approach for, among other things, decomposing the &lt;code&gt;IO&lt;/code&gt; monad into something more modular, so this is by no means a purely academic exercise!&lt;/p&gt;
&lt;p&gt;Voigtländer's monad,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; m a = &lt;span class=&quot;hljs-type&quot;&gt;C&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;. (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) -&amp;gt; m b)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;turns out to be just the right Kan extension of another monad along itself, and can equivalently be thought of as a &lt;code&gt;ContT&lt;/code&gt; that has been universally quantified over its result type.&lt;/p&gt;
&lt;p&gt;The improvement results from the fact that the continuation passing style transformation it applies keeps you from traversing back and forth over the entire tree when performing substitution in the free monad.&lt;/p&gt;
&lt;h2 id=&quot;the-yoneda-lemma&quot;&gt;The Yoneda Lemma&lt;/h2&gt;
&lt;p&gt;Heretofore we've only used right Kan extensions where we have extended a functor along itself. Lets change that:&lt;/p&gt;
&lt;p&gt;Dan Piponi &lt;a href=&quot;http://sigfpe.blogspot.com/2006/11/yoneda-lemma.html&quot;&gt;posted a bit&lt;/a&gt; about the Yoneda lemma a couple of years back, which ended with the observation that the Yoneda lemma says that check and uncheck are inverses:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;check&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b . (a -&amp;gt; b) -&amp;gt; f b)
&lt;span class=&quot;hljs-title&quot;&gt;check&lt;/span&gt; a f = fmap f a

&lt;span class=&quot;hljs-title&quot;&gt;uncheck&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b . (a -&amp;gt; b) -&amp;gt; f b) -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;uncheck&lt;/span&gt; t = t id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that this definition for a right Kan extension just boxes up that universal quantifier in a &lt;code&gt;newtype&lt;/code&gt; and that we could instantiate:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can define &lt;code&gt;check&lt;/code&gt; and &lt;code&gt;uncheck&lt;/code&gt; as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;check'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;check'&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; (\f -&amp;gt; fmap (runIdentity . f) a)

&lt;span class=&quot;hljs-title&quot;&gt;uncheck'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Yoneda&lt;/span&gt; f a -&amp;gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;uncheck'&lt;/span&gt; t = runRan t &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;limits&quot;&gt;Limits&lt;/h2&gt;
&lt;p&gt;We can go on and define categorical limits in terms of right Kan extensions using the &lt;code&gt;Trivial&lt;/code&gt; functor that maps everything to a category with a single value and function. In Haskell, this is best expressed by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f _ = &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;trivialize&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt; b
&lt;span class=&quot;hljs-title&quot;&gt;trivialize&lt;/span&gt; _ = &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lim&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, in Haskell, this gives us a clear operational understanding of categorical limits.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Lim&lt;/span&gt; f a ~ &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt; b) -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This says that we can't use any information of the value &lt;code&gt;a&lt;/code&gt; we supply, or given by the function &lt;code&gt;(a -&amp;gt; Trivial b)&lt;/code&gt; when constructing &lt;code&gt;f b&lt;/code&gt;, but we have to be able to define an &lt;code&gt;f b&lt;/code&gt; for any type &lt;code&gt;b&lt;/code&gt; requested. However, we have no way to get any &lt;code&gt;b&lt;/code&gt; to plug into the functor! So the only (non-cheating) member of &lt;code&gt;Lim Maybe a&lt;/code&gt; is &lt;code&gt;Nothing&lt;/code&gt;, of &lt;code&gt;Lim [] a&lt;/code&gt; is &lt;code&gt;[]&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h2 id=&quot;left-kan-extensions&quot;&gt;Left Kan extensions&lt;/h2&gt;
&lt;p&gt;Left Kan extensions are a bit more obscure to a Haskell programmer, because where right Kan extensions relate to the well-known &lt;code&gt;ContT&lt;/code&gt; monad transformer, the left Kan extension is related to a less well known comonad transformer.&lt;/p&gt;
&lt;p&gt;First, the a Haskell type for the Left Kan extension of &lt;code&gt;h&lt;/code&gt; along &lt;code&gt;g&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h a = forall b. &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is related to the admittedly somewhat obscure &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad-Context.html&quot;&gt;state-in-context comonad transformer&lt;/a&gt;, which I constructed for category-extras.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ContextT&lt;/span&gt; s w a = &lt;span class=&quot;hljs-type&quot;&gt;ContextT&lt;/span&gt;&lt;/span&gt;
  { runContextT :: (w s -&amp;gt; a, w s) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the left Kan extension provides no information about the type &lt;code&gt;b&lt;/code&gt; contained inside of its &lt;code&gt;h&lt;/code&gt; functor and &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;h&lt;/code&gt; are not necessarily the same functor.&lt;/p&gt;
&lt;p&gt;As before we get that &lt;code&gt;Lan g h&lt;/code&gt; is a Functor regardless of what &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;h&lt;/code&gt; are, because we only have to map over the right hand side of the contained function:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; g h) = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (f . g) h
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-comonad-generated-by-a-functor&quot;&gt;The comonad generated by a functor&lt;/h2&gt;
&lt;p&gt;We can also see that the left Kan extension of any functor &lt;code&gt;f&lt;/code&gt; along itself is a comonad, even if f is not a Haskell &lt;code&gt;Functor&lt;/code&gt;. This is of course known as the &lt;em&gt;comonad generated by &lt;code&gt;f&lt;/code&gt;&lt;/em&gt;, or the &lt;em&gt;density comonad of &lt;code&gt;f&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  extract (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f a) = f a
  duplicate (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f ws) = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; f) ws
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;colimits&quot;&gt;Colimits&lt;/h2&gt;
&lt;p&gt;Finally we can derive colimits, by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Colim&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Lan&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Trivial&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then &lt;code&gt;Colim f a ~ exists b. (Trivial b -&amp;gt; a, f b)&lt;/code&gt;, and we can see that operationally, we have an &lt;code&gt;f&lt;/code&gt; of some unknown type &lt;code&gt;b&lt;/code&gt; and for all intents and purposes a value of type &lt;code&gt;a&lt;/code&gt; since we can generate a Trivial b from thin air, so while limits allow only structures without values, colimits allow arbitrary structures, but keep you from inspecting the values in them by existential quantification. So for instance you could apply a length function to a &lt;code&gt;Colim [] a&lt;/code&gt;, but not add up its values.&lt;/p&gt;
&lt;p&gt;You can also build up a covariant analog of the traditional Yoneda lemma using &lt;code&gt;Lan Identity&lt;/code&gt;, but I leave that as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;I've barely scratched the surface of what you can do with Kan extensions, but I just wanted to shine a little light on this dark corner of category theory.&lt;/p&gt;
&lt;p&gt;For more information feel free to explore category-extras. For instance, both right and left Kan extensions along a functor are &lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Functor/HigherOrder.hs&quot;&gt;higher-order functors&lt;/a&gt;, and hence so are Yoneda, Lim, and Colim as defined above.&lt;/p&gt;
&lt;p&gt;Thats all I have time for now.&lt;/p&gt;
&lt;p&gt;Code for right and left Kan extensions, limits, colimits and the Yoneda lemma are all available from category-extras on hackage.&lt;/p&gt;
&lt;p&gt;[Edit: the code has since been refactored to treat Yoneda, CoYoneda, Density and Codensity as separate newtypes to allow for instance both Yoneda and Codensity to be different monads]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/kan-extensions/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Elgot (Co)Algebras</title><link>https://comonad.com/reader/2008/elgot-coalgebras/</link><guid isPermaLink="false">https://comonad.com/reader/2008/elgot-coalgebras/</guid><pubDate>Mon, 19 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 19 May 2008&lt;/p&gt;&lt;span id=&quot;more-60&quot;&gt;&lt;/span&gt;&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Arrow ((|||),(&amp;amp;&amp;amp;&amp;amp;),left)
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;outF&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to talk about a novel recursion scheme that hasn't received a lot of attention from the Haskell community and its even more obscure dual -- which is necessarily more obscure because I believe this is the first time anyone has talked about it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.iti.cs.tu-bs.de/~adamek/adamek.html&quot;&gt;Jiri Adámek&lt;/a&gt;, &lt;a href=&quot;http://www.iti.cs.tu-bs.de/~milius/&quot;&gt;Stefan Milius&lt;/a&gt; and &lt;a href=&quot;http://math.feld.cvut.cz/velebil/&quot;&gt;Jiri Velebil&lt;/a&gt; have done a lot of work on &lt;a href=&quot;http://arxiv.org/abs/cs/0609040&quot;&gt;Elgot algebras&lt;/a&gt;. Here I'd like to translate them into Haskell, dualize them, observe that the dual can encode primitive recursion, and provide some observations.&lt;/p&gt;
&lt;p&gt;You can kind of think an Elgot algebra as a hylomorphism that cheats.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;elgot&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f b -&amp;gt; b) -&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; b (f a)) -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;elgot&lt;/span&gt; phi psi = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = (id ||| phi . fmap h) . psi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you look at the signature for a hylomorphism:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;hylo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f b -&amp;gt; b) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;hylo&lt;/span&gt; phi psi = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = phi . fmap h . psi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can see that an Elgot algebra is basically a hylomorphism that is allowed to shortcircuit the infinite tower of fmaps and return an intermediate result directly.&lt;/p&gt;
&lt;p&gt;In some sense you can say that the coalgebra-like side of the hylomorphism is no longer oblivious to the algebra used to deconstruct the intermediate result.&lt;/p&gt;
&lt;p&gt;We can take the Elgot algebra and dualize it to get a novel construction where the algebra-like side is no longer oblivious to the coalgebra. This allows your algebra to cheat and just use the intermediate results constructed by the anamorphism to return an answer. I'll choose to call this co-(Elgot algebra) an Elgot coalgebra in the sequel.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;coelgot&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; ((a, f b) -&amp;gt; b) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;coelgot&lt;/span&gt; phi psi = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = phi . (id &amp;amp;&amp;amp;&amp;amp; fmap h . psi)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a lot of ways an Elgot algebra resembles Vene and Uustalu's &lt;a href=&quot;http://citeseer.ist.psu.edu/vene98functional.html&quot;&gt;apomorphism&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;apo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f) a)) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;apo&lt;/span&gt; psi = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; . fmap h . (fmap &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; . outF ||| psi) . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, we have 'unfixed' the algebra to be used from InF to something more general and the layering of Either and f is different.&lt;/p&gt;
&lt;p&gt;Now, a generalized apomorphism does something similar entangling two coalgebras, but the signature doesn't quite match up either, since a generalized apomorphism uses an F-coalgebras and an F-(b + _)-monadic coalgebra.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_apo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (b -&amp;gt; f b) -&amp;gt; (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; b a)) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;g_apo&lt;/span&gt; g f = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; . fmap h . (fmap &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; . g ||| f) . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly a zygomorphism, or more generally a &lt;a href=&quot;http://dbappl.cs.utwente.nl/Publications/PaperStore/db-utwente-0000003537.pdf&quot;&gt;mutumorphism&lt;/a&gt; entangles two algebras.&lt;/p&gt;
&lt;p&gt;An Elgot algebra occupies a somewhat rare spot in the theory of constructive algorithmics or recursion schemes in that it while it mixes an algebra with a coalgebra like a hylomorphism or metamorphisms, it entangles them in a novel way.&lt;/p&gt;
&lt;p&gt;If we specialize the Elgot algebra by fixing its algebra to InF we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;elgot_apo&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f) (f a)) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;elgot_apo&lt;/span&gt; psi = h &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt; h = (id ||| &lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; . fmap h) . psi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that the type is now closely related to that of an apomorphism with some slight changes in design decisions. Instead of wrapping a functor around further seeds, a, or a finished structure, this specialized Elgot algebra returns the finished structure directly or an f wrapped around seeds.&lt;/p&gt;
&lt;h2 id=&quot;the-good&quot;&gt;The Good&lt;/h2&gt;
&lt;p&gt;So can we convert between an apomorphism and an Elgot algebra? For a somewhat circuitous path to that answer lets recall the &lt;a href=&quot;https://comonad.com/reader/2008/deriving-strength-from-laziness/&quot;&gt;definition of strength&lt;/a&gt; from my post a couple of weeks ago. Flipping the arguments and direction of application for strength to simplify what is coming we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;strength'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; t -&amp;gt; f a -&amp;gt; f (t, a)
&lt;span class=&quot;hljs-title&quot;&gt;strength'&lt;/span&gt; fa b = fmap ((,)b) fa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that in hand we quickly find that we can rederive &lt;a href=&quot;http://en.wikipedia.org/wiki/Paramorphism&quot;&gt;paramorphisms&lt;/a&gt; (and hence primitive recursion) from the novel notion of an Elgot coalgebra that we defined above by leaning on the strength of our functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;para&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f (&lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f, c) -&amp;gt; c) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; c
&lt;span class=&quot;hljs-title&quot;&gt;para&lt;/span&gt; f = coelgot (f . uncurry strength') outF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This result tells us that the shiny new Elgot coalgebras we defined above are strong enough to encode primitive recursion when working in Haskell.&lt;/p&gt;
&lt;h2 id=&quot;the-bad&quot;&gt;The Bad&lt;/h2&gt;
&lt;p&gt;This tempts us to try to derive apomorphisms from Elgot algebras using the dual case, costrength. However, if you'll recall from my previous post on comonadic costrength, we can't do that in general. The result is only defined for Traversable functors; not every functor is costrong in Haskell!&lt;/p&gt;
&lt;p&gt;Consequently and counterintuitively, though we can define a paramorphism in terms of Elgot coalgebras, we can only define an apomorphism in terms of Elgot algebras for traversable functors.&lt;/p&gt;
&lt;h2 id=&quot;the-ugly&quot;&gt;The Ugly&lt;/h2&gt;
&lt;p&gt;Now, worse news. Since the tower of functors we build up doesn't run off to infinity we lose the ability to generalize Elgot (co)algebras using the same machinery we can use to generalize the various traditional recursion schemes by parameterizing it by a (co)monad and distributive law.&lt;/p&gt;
&lt;p&gt;At least the straightforward translation fails. For instance in the case of an Elgot algebra, the obvious addition would be to allow for the algebra (f a -&amp;gt; a) to be replaced with a F-W-comonadic algebra (f (w a) -&amp;gt; a) for some comonad w. However, attempts to do so run afoul of the fact that the coalgebra-like structure feeds us an 'a' not a 'w a'. We can of course change the signature of the coalgebra to give us the comonad, but the breakdown of modularity is unfortunate.&lt;/p&gt;
&lt;p&gt;Similary, parameterizing the coalgebra-like structure with a monad requires the ability to distribute the monad over Either b to get to where it can apply the distributive law for the base functor f. Interestingly the Either monad works, which gives us ways to compose Elgot (co)algebras, but that is a story for another day.&lt;/p&gt;
&lt;p&gt;As usual there is a tradeoff in expressivity in one area to compensate for gains in another, but this manner of entangling provides us with a new set of possibilities to explore.&lt;/p&gt;
&lt;p&gt;Code for Elgot algebras and Elgot coalgebras has been included in &lt;a href=&quot;https://hackage.haskell.org/package/category-extras-0.50.3&quot;&gt;category-extras&lt;/a&gt; as of release 0.50.3 as &lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Functor/Algebra/&quot;&gt;Control.Functor.Algebra.Elgot&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now available from hackage.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/elgot-coalgebras/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Forgetful Laziness</title><link>https://comonad.com/reader/2008/forgetful-laziness/</link><guid isPermaLink="false">https://comonad.com/reader/2008/forgetful-laziness/</guid><pubDate>Fri, 16 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 16 May 2008&lt;/p&gt;&lt;span id=&quot;more-59&quot;&gt;&lt;/span&gt;&lt;p&gt;Does anyone know of any work on &quot;forgetful laziness?&quot;&lt;/p&gt;
&lt;p&gt;The basic idea being that for each thunk instead of overwriting it with the answer as usual in call-by-need, you'd just write a forwarding pointer, and allow GC to collect the answers over time.&lt;/p&gt;
&lt;p&gt;This results in recalculation and may be subject to thrashing, so the obvious fix would be either&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a 'forget at most once' policy, which would only mitigate the kind of memory leaks you get from laziness under limited conditions, but which has a worst case payout of doubling the workload or&lt;/li&gt;
&lt;li&gt;an exponential backoff on how often you'll try to recollect a given value, which should preserve for practical purposes the asymptotic behavior of any algorithm, but with a much larger constant for pathological access patterns. [Edit: it may affect asymptotic behavior, because you could lose sharing]&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This would allow the recollection of large CAFs, etc. eventually once they had bitrotted long enough.&lt;/p&gt;
&lt;p&gt;Not sure if its worth the cost of recalculating and of storing any backoff counter, but most of the horror stories you hear about Haskell center around its occasional horrific memory usage profile.&lt;/p&gt;
&lt;p&gt;Tuning points might include studying average thunk lifetimes to construct thunk access profiles rather than use a naive exponential backoff.&lt;/p&gt;
&lt;p&gt;It also may exascerbate the opposite problem where naive code often builds up a tower of thunks it needs to evaluate all at once in order to provide an answer (i.e. when working with a lazy accumulating parameter).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/forgetful-laziness/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Generatingfunctorology</title><link>https://comonad.com/reader/2008/generatingfunctorology/</link><guid isPermaLink="false">https://comonad.com/reader/2008/generatingfunctorology/</guid><pubDate>Wed, 14 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 14 May 2008&lt;/p&gt;&lt;span id=&quot;more-58&quot;&gt;&lt;/span&gt;&lt;p&gt;Ok, I decided to take a step back from my flawed approach in the &lt;a href=&quot;https://comonad.com/reader/2008/towards-formal-power-series-for-functors/&quot;&gt;last post&lt;/a&gt; and play with the idea of power series of functors from a different perspective.&lt;/p&gt;
&lt;p&gt;I dusted off my copy of Herbert Wilf's &lt;a href=&quot;http://www.math.upenn.edu/~wilf/DownldGF.html&quot;&gt;generatingfunctionology&lt;/a&gt; and switched goals to try to see some well known recursive functors or &lt;a href=&quot;http://www.cas.mcmaster.ca/~carette/species/msfp08_species.pdf&quot;&gt;species&lt;/a&gt; as formal power series. It appears that we can pick a few things out about the generating functions of polynomial functors.&lt;/p&gt;
&lt;p&gt;As an example:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; x = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok. We're done. Thank you very much. I'll be here all week. Try the veal...&lt;/p&gt;
&lt;p&gt;For a more serious example, the formal power series for the list [x] is just a &lt;a href=&quot;http://en.wikipedia.org/wiki/Geometric_series&quot;&gt;geometric series&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;[x] = mu y . &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x y  &lt;span class=&quot;hljs-comment&quot;&gt;-- the mu here is a pleasant fiction, more below&lt;/span&gt;
    = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x (...)))
    = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x + x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; + ...
    = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;/(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given the power series of a functor, its nth coefficient * n! tells you how many distinguishable ways its constructors can house n values. If we see that a list of n values can be permuted n! ways this has some interesting possibilities for linearizing the storage of some functors. The list case is boring, we can store a &lt;em&gt;finite&lt;/em&gt; list of n elements by supplying the length of the array and an array of n elements, hence (among other reasons) the mu above.&lt;/p&gt;
&lt;p&gt;Lets try decorated binary trees:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;Leaf&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;Node&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;) x (&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;x&lt;/span&gt;)&lt;/span&gt;

&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; x = mu y. &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x * y * y
       = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x * (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x * (...)^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
       = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x + 2x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + 5x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; + 14x^&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; + 42x^&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; + ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out the coefficients of our generating function are the &lt;a href=&quot;http://en.wikipedia.org/wiki/Catalan_number&quot;&gt;Catalan numbers&lt;/a&gt;, &lt;a href=&quot;http://www.research.att.com/~njas/sequences/A000108&quot;&gt;A000108&lt;/a&gt;, commonly denoted C(n), which happen to be well known for among other things, being the number of ways you can build a binary tree of n nodes.&lt;/p&gt;
&lt;p&gt;This tells us we could store a tree by storing a number &lt;em&gt;n&lt;/em&gt; of nodes it contains, an array of that many nodes, and an index 0 &amp;lt; = i &amp;lt; C(n) to tell you which particular tree you selected. Not that this is likely to be an incredibly time-efficient encoding, but you could then fmap over the tree by just fmapping over your array.&lt;/p&gt;
&lt;p&gt;For a formal power series,&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∞&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x) = \sum_{i=0}^{\infty} a_n x^n = a_0 + a_1 x + a_2 x^2 + ... &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.104em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8043em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;∞&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.9641em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.1056em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;its derivative is given by differentiating the series term by term:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∞&lt;/mi&gt;&lt;/msubsup&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f'(x) = \sum_{i=1}^{\infty} n a_n x^{n - 1} = a_1 + 2 a_2 x + 3 a_3 x^2 + ...&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0019em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.1138em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8043em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;∞&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7944em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.9641em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.1056em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Consequently we can take the derivative of a list:&lt;/p&gt;
&lt;p&gt;([]') x = 1 + 2x + 3x^2 + ... = 1/(1-x)^2 = ([] :*: []) x&lt;/p&gt;
&lt;p&gt;and rederive the notion that a derivative/one hole context of a list can be represented by a pair of lists.&lt;/p&gt;
&lt;p&gt;If we step slightly outside of the Haskell users' comfort zone and notion of a Functor and allow other Species, we get (as noted by apfelmus the other day) that Exp a is just a bag of elements with no predetermined order.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; x = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x + x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;! + x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;! + ... = &lt;span class=&quot;hljs-type&quot;&gt;Bag&lt;/span&gt; x

&lt;span class=&quot;hljs-type&quot;&gt;Since&lt;/span&gt; there are n! ways to order n elements and &lt;span class=&quot;hljs-type&quot;&gt;Bag&lt;/span&gt; manages to forget that information, we can get a feeling for the meaning &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; division &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; this setting.

&lt;span class=&quot;hljs-type&quot;&gt;Similarly&lt;/span&gt; we can define:
&amp;lt;pre lang=&lt;span class=&quot;hljs-string&quot;&gt;&quot;haskell&quot;&lt;/span&gt;&amp;gt;
&lt;span class=&quot;hljs-type&quot;&gt;Sinh&lt;/span&gt; x = x + x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;! + ... &lt;span class=&quot;hljs-comment&quot;&gt;-- a Bag of some odd number of elements.&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;Cosh&lt;/span&gt; x = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;! + ... &lt;span class=&quot;hljs-comment&quot;&gt;--  a Bag of some even number of elements.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then by construction:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Exp&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Cosh&lt;/span&gt; :+: &lt;span class=&quot;hljs-type&quot;&gt;Sinh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The derivative of Exp is Exp, of Cosh is Sinh, of Sinh is Cosh, all as you would expect.&lt;/p&gt;
&lt;p&gt;We can handle other species as well:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Cycle&lt;/span&gt; a = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; + x^&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;/&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; + ... &lt;span class=&quot;hljs-comment&quot;&gt;-- cycles&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;Cycle_n&lt;/span&gt; a = x^n/n &lt;span class=&quot;hljs-comment&quot;&gt;-- cycles of n elements&lt;/span&gt;
&lt;span class=&quot;hljs-type&quot;&gt;Bag_n&lt;/span&gt; a = x^n/n!  &lt;span class=&quot;hljs-comment&quot;&gt;-- bags of n elements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That said, there seem to be some problems, not every functor is well behaved in this way. Lets take for instance the type of natural numbers given by the functor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Z&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the recurrence blows up, the coefficient for 0 is &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;ℵ&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\aleph_0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;ℵ&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;!&lt;/p&gt;
&lt;p&gt;Similarly, if we parameterized a functor on another value we have to deal with the number of cases that other value can denote.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a x = |a| + x
(a,x) = |a| x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is both good and bad, using the above, we can quickly establish an isomorphism between Either () and the Maybe Functor, but we blow up again for Either Integer. This gets even worse if we allow 'functors in space.' (i.e. functors that can contain functions)&lt;/p&gt;
&lt;p&gt;On the other extreme, we might modify our tree example and remove the leaves, yielding infinite decorated cotrees.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Tree&lt;/span&gt; x = nu y. x * y * y
       = x * (x * (...)^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
       = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; + 0x + 0x^&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + 0x^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; + ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then a_n = 0 for all n in the natural numbers, so you can't use the coefficients of the generating function to tell you about the behavior of an infinite structure! It would appear that the generating function of a functor does not capture what happens in the greatest fixed point case, so we can only use generating functions to describe the behavior of data defined with mu, not in general codata defined by nu.&lt;/p&gt;
&lt;p&gt;The Bags and Cycles above are nice examples, but if we wanted to rule out the non-polynomial Functors (from the Haskell perspective) in the above then we can simply limit ourselves to &lt;a href=&quot;http://en.wikipedia.org/wiki/Generating_function#Ordinary_generating_function_2&quot;&gt;ordinary generating functions&lt;/a&gt; with natural number coefficients, that is to say generating functions of the form:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∞&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x) = \sum_{i=0}^{\infty} a_n x^n = a_0 + a_1 x + a_2 x^2 + ... &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.104em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8043em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;∞&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.9641em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.1056em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To choose to admit bags, cycles and other species etc. then you need merely also permit &lt;a href=&quot;http://en.wikipedia.org/wiki/Generating_function#Exponential_generating_function_2&quot;&gt;exponential generating functions&lt;/a&gt; with natural coefficients, that is to say, generating functions of the form:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∞&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msup&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;!&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;!&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;!&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f(x) = \sum_{i=0}^{\infty} a_n x^n / n! = a_0 + a_1 x / 1! + a_2 x^2 / 2! + ... &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.104em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8043em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;∞&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6644em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/2&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.1056em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/generatingfunctorology/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Towards Formal Power Series for Functors</title><link>https://comonad.com/reader/2008/towards-formal-power-series-for-functors/</link><guid isPermaLink="false">https://comonad.com/reader/2008/towards-formal-power-series-for-functors/</guid><pubDate>Tue, 13 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 13 May 2008&lt;/p&gt;&lt;span id=&quot;more-57&quot;&gt;&lt;/span&gt;&lt;p&gt;The post below will only compile on a version of GHC &amp;gt;= 6.9, since it uses type families.&lt;/p&gt;
&lt;p&gt;There has been a lot of posting recently about automatic differentiation in Haskell, and I wanted to try the same thing with functors in the spirit of Conor McBride's &lt;a href=&quot;http://strictlypositive.org/CJ.pdf&quot;&gt;Clowns to the Left of me, Jokers to the Right&lt;/a&gt; and &lt;a href=&quot;http://citeseer.ist.psu.edu/472190.html&quot;&gt;The derivative of a regular type is its type of one hole contexts&lt;/a&gt;, figuring that a Power Series could fully generalize Christophe Poucet's &lt;a href=&quot;http://notvincenz.blogspot.com/2007/07/higher-order-zippers.html&quot;&gt;Higher Order Zippers&lt;/a&gt;, and might provide me with a neat extension to the zipper comonadic automata I've been aluding to recently.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Derivatives &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Identity
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Arrow ((+++),(***),(&amp;amp;&amp;amp;&amp;amp;))
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Data.Monoid
&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt; :.:
&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt; :*:
&lt;span class=&quot;hljs-keyword&quot;&gt;infixl&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt; :+:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To avoid importing &lt;a href=&quot;https://hackage.haskell.org/package/category-extras-0.44.4&quot;&gt;category-extras&lt;/a&gt; and keep this post self-contained (modulo GHC 6.9!), we'll define some preliminaries such as Bifunctors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap :: (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; d) -&amp;gt; f a b -&amp;gt; f c d
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; (,) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap f g ~(a,b) = (f a, g b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap f _ (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (f a)
  bimap _ g (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (g b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Constant functors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; show _ = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Void&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; k a = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runConst&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt; } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; ()&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; . runConst
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and functor products and coproducts:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; p f g a = &lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runLift&lt;/span&gt; ::  &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; (:+:) = &lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; (:*:) = &lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; (,)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  show (&lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; x) = &lt;span class=&quot;hljs-string&quot;&gt;&quot;(Lift (&quot;&lt;/span&gt; ++ show x ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;))&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Lift&lt;/span&gt; . bimap (fmap f) (fmap f) . runLift
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and finally functor composition&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :.: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) a = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runComp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) } &lt;span class=&quot;hljs-keyword&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :.: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; . fmap (fmap f) . runComp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So then, an ideal type for repeated differentiation would look something like the following, for some definition of D.&lt;/p&gt;
&lt;p&gt;[Edit: sigfpe pointed out, quite rightly, that this is just repeated differentiation, and apfelmus pointed out that it not a power series, because I have no division!]&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AD&lt;/span&gt; f a  = &lt;span class=&quot;hljs-type&quot;&gt;AD&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runAD&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;,  &lt;span class=&quot;hljs-type&quot;&gt;AD&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a first crack at D, you might be tempted to just go with a type family:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;{-
type family D (f :: * -&amp;gt; *) :: * -&amp;gt; *
type instance D Identity = One
type instance D (Const k) = Zero
type instance D (f :+: g) = D f :+: D g
type instance D (f :*: g) = f :*: D g :+: D f :*: g
type instance D (f :.: g) = (D f :.: g) :*: D g
-}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This could take you pretty far, but unfortunately doesn't adequately provide you with any constraints on the type so that we can treat AD f as a functor.&lt;/p&gt;
&lt;p&gt;So, we'll go with:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :: * -&amp;gt; *) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f :: * -&amp;gt; *&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and cherry pick the instances necessary to handle the above cases:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;One&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;k&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;Zero&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) = &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f :+: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; g&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :*: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :*: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) = f :*: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; g :+: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; f :*: g&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :.: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :.: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) = (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :.: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) :*: &lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With those instances in hand, we can define the definition of a Functor for the automatic differentiation of a Functor built out of these primitives:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Derivable&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;AD&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;AD&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Power&lt;/span&gt; . bimap (fmap f) (fmap f) . runPower
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, here is where I run out of steam, because any attempt to actually use the construct in question blows the context stack because the recursion for Functor (AD f) isn't well founded and my attempts to force it to be so through overlapping-instances have thus-far failed.&lt;/p&gt;
&lt;p&gt;Thoughts?&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://comonad.com/haskell/Derivatives.hs&quot;&gt;Source Code&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/towards-formal-power-series-for-functors/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Just Fokkinga Abide</title><link>https://comonad.com/reader/2008/just-fokkinga-abide/</link><guid isPermaLink="false">https://comonad.com/reader/2008/just-fokkinga-abide/</guid><pubDate>Wed, 07 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 7 May 2008&lt;/p&gt;&lt;p&gt;I did some digging and found the universal operations mentioned in the last couple of posts: unzip, unbizip and counzip were referenced as abide&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{}_F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4783em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, abide&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;†&lt;/mo&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{}_\dagger&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6222em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mbin mtight&quot;&gt;†&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and coabide&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{}_F&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4783em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; -- actually, I was looking for something else, and this fell into my lap.&lt;/p&gt;
&lt;p&gt;They were apparently named for a notion defined by Richard Bird back in:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;R.S. Bird. Lecture notes on constructive functional programming. In M. Broy, editor, Constructive Methods in Computing Science. International Summer School directed by F.L. Bauer [et al.], Springer Verlag, 1989. NATO Advanced Science Institute Series (Series F: Computer and System Sciences Vol. 55).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The notion can be summed up by defining that two binary operations &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbin{\htmlClass{vertical-operator}{\ominus}}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;enclosing vertical-operator&quot;&gt;&lt;span class=&quot;mord&quot;&gt;⊖&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\ominus&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;⊖&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;strong&gt;abide&lt;/strong&gt; if for all a, b, c, d:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&lt;mo&gt;⊖&lt;/mo&gt;&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(a \ominus b) \mathbin{\htmlClass{vertical-operator}{\ominus}} (c \ominus d) = (a \mathbin{\htmlClass{vertical-operator}{\ominus}} c) \ominus (b \mathbin{\htmlClass{vertical-operator}{\ominus}} d)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⊖&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;enclosing vertical-operator&quot;&gt;&lt;span class=&quot;mord&quot;&gt;⊖&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⊖&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;enclosing vertical-operator&quot;&gt;&lt;span class=&quot;mord&quot;&gt;⊖&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;⊖&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;&lt;span class=&quot;enclosing vertical-operator&quot;&gt;&lt;span class=&quot;mord&quot;&gt;⊖&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;There is a cute pictorial explanation of this idea in &lt;a href=&quot;http://dbappl.cs.utwente.nl/Publications/PaperStore/db-utwente-404F4540.pdf&quot;&gt;Maarten Fokkinga's remarkably readable Ph.D dissertation&lt;/a&gt; on p. 20.&lt;/p&gt;
&lt;p&gt;The idea appears again on p.88 as part of the famous 'banana split' theorem, and then later on p90 the above names above are given along with the laws:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f &amp;amp;&amp;amp;&amp;amp; fmap g = unfzip . fmap (f &amp;amp;&amp;amp;&amp;amp; g)
&lt;span class=&quot;hljs-title&quot;&gt;bimap&lt;/span&gt; f g &amp;amp;&amp;amp;&amp;amp; bimap h j = unbizip . bimap (f &amp;amp;&amp;amp;&amp;amp; h) (g &amp;amp;&amp;amp;&amp;amp; j)
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f ||| fmap g = fmap (f ||| g) . counfzip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That said the cases when the inverse operations exist do not appear to be mentioned in these sources.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/just-fokkinga-abide/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cozipping</title><link>https://comonad.com/reader/2008/cozipping/</link><guid isPermaLink="false">https://comonad.com/reader/2008/cozipping/</guid><pubDate>Mon, 05 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 5 May 2008&lt;/p&gt;&lt;span id=&quot;more-55&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;a href=&quot;http://twan.home.fmf.nl/&quot;&gt;Twan van Laarhoven&lt;/a&gt; &lt;a href=&quot;https://comonad.com/reader/2008/zipping-and-unzipping-functors/#comments&quot;&gt;pointed out&lt;/a&gt; that fzip from the other day is a close cousin of applicative chosen to be an inverse of the universal construction 'unfzip'.&lt;/p&gt;
&lt;p&gt;During that post I also put off talking about the dual of zipping, so I figured I'd bring up the notion of choosing a notion of 'cozipping' by defining it as an inverse to a universally definable notion of 'counzipping'.&lt;/p&gt;
&lt;p&gt;[Edit: Twan pointed out I had flipped which was the dual of zip, revised]&lt;/p&gt;
&lt;p&gt;Abusing the new category-extras to avoid making an enormous post and recycling the constructions from the previous post, we can define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# LANGUAGE FlexibleInstances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Control.Functor.Cozip &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Arrow ((|||),(+++))
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Identity
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Bifunctor.Biff
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Bifunctor.Fix
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same inverse question leads to some observations about the dual of fzip as opposed to its inverse.&lt;/p&gt;
&lt;p&gt;We could call them cozip and uncozip for lack of a better name, but as we will see cozip is more accurately about deciding classifying the contents of the functor, so maybe deserves a better, more evocative name like 'decide' or 'cleave'.&lt;/p&gt;
&lt;p&gt;counzip and its bifunctorial equivalent always exist.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;counzip&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (f a) (f b) -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b)
&lt;span class=&quot;hljs-title&quot;&gt;counzip&lt;/span&gt; = fmap &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; ||| fmap &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;counbizip&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (f a c) (f b d) -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c d)
&lt;span class=&quot;hljs-title&quot;&gt;counbizip&lt;/span&gt; = bimap &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; ||| bimap &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But there are some cases where its inverse doesn't exist, such as the Reader/State monads, or where uncozip only has a right inverse like with Maybe/Either.&lt;/p&gt;
&lt;p&gt;Counzipping basically demonstrates the fact that if I have either a container of a's or a container of b's, I can treat that as a container of 'as or bs', giving up the knowledge that the container contains entirely one or the other.&lt;/p&gt;
&lt;p&gt;Its inverse describes the cases where we can recover this information.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip :: f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (f a) (f b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip = bimap &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; . runIdentity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, in general a functor that has more than one 'hole' will not be recoverable because one hole could contain an a, and the other could contain a b, so you would be unable to perform the split. Futhermore unless there is a way to decide the value contained you'll never be able to tell which branch of the Either to return, so functors like the reader/state monads are out.&lt;/p&gt;
&lt;p&gt;However, this does not close the door to a few other functors:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; ((,)c) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip (c,ab) = bimap ((,)c) ((,)c) ab

&lt;span class=&quot;hljs-comment&quot;&gt;-- ambiguous choice&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip = maybe (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;) (bimap &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt;)
&lt;span class=&quot;hljs-comment&quot;&gt;-- cozip = maybe (Right Nothing) (bimap Just Just)&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- ambiguous choice&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;c&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip = (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;) ||| bimap &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- cozip = (Right . Left) ||| bimap Right Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the definitions for Maybe and (Either c) had to 'choose' where to put the &quot;Nothing/Left&quot; term. Consequently they are only right-inverses of counzip.&lt;/p&gt;
&lt;p&gt;You can also go and generate one that says that the functor coproduct of a pair of cozippable functors is cozippable, just like the functor product of a pair of zippable functors is zippable (given by the construction given for BiffB the other day).&lt;/p&gt;
&lt;p&gt;Finally, the only surprising instance is for the free monad of a cozippable functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- instance Cozip f =&amp;gt; Cozip (Free f) where&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cozip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   cozip (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a))))) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a))))
   cozip (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a))))) = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a))))
   cozip (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;))) = ((&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;) +++ (&lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;)) (cozip (fmap cozip &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This says that even though Either is not 'bicozippable' - which appears to be an ill-defined concept - we can build up a general cozip for the free monad of an cozippable functor. The reason is that if your functor only has one place to put a value, then putting the free monad in that place just means that you have to search longer.&lt;/p&gt;
&lt;p&gt;So, we've found the fact that free monads of cozippable functors are cozippable, in contrast to the conclusion of the other day that cofree comonads of zippable functors are zippable.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/cozipping/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Zipping and Unzipping Functors</title><link>https://comonad.com/reader/2008/zipping-and-unzipping-functors/</link><guid isPermaLink="false">https://comonad.com/reader/2008/zipping-and-unzipping-functors/</guid><pubDate>Sun, 04 May 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 4 May 2008&lt;/p&gt;&lt;span id=&quot;more-54&quot;&gt;&lt;/span&gt;&lt;p&gt;Kefer asked a question in the comments of my post about &lt;a href=&quot;https://comonad.com/reader/2008/deriving-strength-from-laziness/&quot;&gt;(co)monadic (co)strength&lt;/a&gt; about Uustalu and Vene's ComonadZip class from p157 of &lt;a href=&quot;http://cs.ioc.ee/~tarmo/papers/cefp05.pdf&quot;&gt;The Essence of Dataflow Programming&lt;/a&gt;. The class in question is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ComonadZip&lt;/span&gt; w &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
     czip :: f a -&amp;gt; f b -&amp;gt; f (a, b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In response I added &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Zip.html&quot;&gt;Control.Functor.Zip&lt;/a&gt; [&lt;a href=&quot;https://comonad.com/haskell/category-extras/src/Control/Functor/Zip.hs&quot;&gt;Source&lt;/a&gt;] to my nascent rebundled version of category-extras, which was posted up to hackage earlier today.&lt;/p&gt;
&lt;p&gt;Putting aside the dual operation for the moment, we can dispense with the inverse of zip quite simply, for much the same reason that every functor in Haskell is strong, every functor in haskell is unzippable:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;unfzip&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f (a, b) -&amp;gt; (f a, f b)
&lt;span class=&quot;hljs-title&quot;&gt;unfzip&lt;/span&gt; = fmap fst &amp;amp;&amp;amp;&amp;amp; fmap snd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other hand the question of what Functors are zippable is a little trickier. Allowing for a circular definition between fzip and fzipWith we can start with the following class for which you have to implement at least one of fzip or fzipWith.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzip :: f a -&amp;gt; f b -&amp;gt; f (a, b)
  fzip = fzipWith (,)
  fzipWith :: (a -&amp;gt; b -&amp;gt; c) -&amp;gt; f a -&amp;gt; f b -&amp;gt; f c
  fzipWith f &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs = fmap (uncurry f) (fzip &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we set aside the restriction that we only be able to Zip a comonad, and simply require that if the functor in question is a comonad, then it is a &quot;symmetric semi-monoidal comonad&quot;, which is to say that zipping and then extracting yields the same result as extracting from each separately. You may note a lot of similarity in the above to the definition for &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Functor-Zap.html&quot;&gt;Control.Functor.Zap&lt;/a&gt; the Dual functor from &lt;a href=&quot;https://comonad.com/reader/2008/the-cofree-comonad-and-the-expression-problem/&quot;&gt;the other day&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, we can throw ourselves with reckless abandon at the easy cases:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; (f a b)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzip = zip
  fzipWith = zipWith
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; (f a b)
  fzipWith f _ _ = &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we note that Either causes us to break down, we can't handle the 'mixed' cases of Left and Right cleanly. We can however use the same 'cheat' that makes the Writer Monad work, however, and rely on an instance of Monoid, and leaving the left hand side of the bifunctor unchanged to enable us to define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (mappend a b)
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; b
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a
  fzipWith f (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (f a b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and similarly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monoid&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; ((,)a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzipWith f (a, c) (b, d) = (mappend a b, f c d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately the instance for ((,)a) is a little less than satisfying, what we really want to say there is that we have a &lt;a href=&quot;https://comonad.com/source/unavailable/haskell-1.html&quot;&gt;Bifunctor&lt;/a&gt; and that it has two parameters that can be zipped together:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizip :: p a c -&amp;gt; p b d -&amp;gt; p (a,b) (c,d)
  bizip = bizipWith (,) (,)
  bizipWith :: (a -&amp;gt; b -&amp;gt; e) -&amp;gt; (c -&amp;gt; d -&amp;gt; f) -&amp;gt; p a c -&amp;gt; p b d -&amp;gt; p e f
  bizipWith f g &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs = bimap (uncurry f) (uncurry g) (bizip &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can define a more satisfying instance for (,):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; (,) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizipWith f g (a,b) (c,d) = (f a c, g b d)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, by its very nature, an instance for Either eludes us.&lt;/p&gt;
&lt;p&gt;Now, we can define a &quot;Bifunctor-Functor-Functor Bifunctor&quot; transformer that takes a bifunctor and a pair of functors to wrap it around, and derives a new bifunctor and lift the zippability of each of the parts to the zippability of the whole:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; p f g a b = &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runBiffB&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap f g = &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; . bimap (fmap f) (fmap g) . runBiffB
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizipWith f g &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs = &lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; $ bizipWith (fzipWith f) (fzipWith g) (runBiffB &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) (runBiffB bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What is interesting about this is that the &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Comonad-Cofree.html&quot;&gt;cofree comonad&lt;/a&gt; and &lt;a href=&quot;https://comonad.com/haskell/category-extras/dist/doc/html/category-extras/Control-Monad-Free.html&quot;&gt;free monad&lt;/a&gt; can be defined in terms of BiffB given a definition for the &lt;a href=&quot;https://comonad.com/source/unavailable/haskell-2.html&quot;&gt;fixed point of a bifunctor&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; s a = &lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;outB&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; s =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; . bimap f (fmap f) . outB

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; (,) &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; f) a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;BiffB&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can define that the fixed point of a zippable bifunctor is a zippable functor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; p =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FixB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fzipWith f &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs = &lt;span class=&quot;hljs-type&quot;&gt;InB&lt;/span&gt; $ bizipWith f (fzipWith f) (outB &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) (outB bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then it immediately follows by the construction for BiffB that every Cofree Comonad of a zippable base functor is Zippable because they are the fixed point of BiffB (,) Identity f. and since (,) is zippable and Identity is zippable, then given f zippable the base bifunctor is zippable, so Cofree f is zippable.&lt;/p&gt;
&lt;p&gt;On the other hand, we do not get the same result for the &lt;a href=&quot;https://comonad.com/reader/2008/monads-for-free/&quot;&gt;Free Monad&lt;/a&gt;, because it is built over BiffB Either Identity f, and Either is not a zippable bifunctor.&lt;/p&gt;
&lt;p&gt;We can define some other functors and bifunctors which are zippable, i.e. we can define a &lt;a href=&quot;https://comonad.com/source/unavailable/haskell-0.html&quot;&gt;&quot;functor-wrapped bifunctor bifunctor&quot;&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; f p a b = &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runFunctorB&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;b&lt;/span&gt;) }&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;liftFunctorB&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (p a b -&amp;gt; p c d) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; f p a b -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; f p c d
&lt;span class=&quot;hljs-title&quot;&gt;liftFunctorB&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; . fmap f . runFunctorB
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap f g = liftFunctorB (bimap f g)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Zip&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bizip&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;p&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizipWith f g &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs = &lt;span class=&quot;hljs-type&quot;&gt;FunctorB&lt;/span&gt; $ fzipWith (bizipWith f g) (runFunctorB &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) (runFunctorB bs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But the general pattern was set by Either and Maybe. Whenever your functor has a branch you need a way to uniquely determine the way the constant terms combine.&lt;/p&gt;
&lt;p&gt;While I think the above yields a pleasingly generic version of zip. I do not believe that I have exhausted the set of possible instances, but yielding them automatically for cofree comonads of zippable functors, and hence for rose trees, streams, was rather nice.&lt;/p&gt;
&lt;p&gt;If you have any other instances of note, I would welcome the insight.&lt;/p&gt;
&lt;p&gt;[&lt;a href=&quot;https://hackage.haskell.org/package/category-extras-0.44.1&quot;&gt;category-extras-0.44.1&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/zipping-and-unzipping-functors/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Deriving Strength from Laziness</title><link>https://comonad.com/reader/2008/deriving-strength-from-laziness/</link><guid isPermaLink="false">https://comonad.com/reader/2008/deriving-strength-from-laziness/</guid><pubDate>Wed, 30 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 April 2008&lt;/p&gt;&lt;span id=&quot;more-52&quot;&gt;&lt;/span&gt;&lt;p&gt;No, this isn't some uplifting piece about deriving courage from sloth in the face of adversity.&lt;/p&gt;
&lt;p&gt;What I want to talk about is &lt;strong&gt;monadic&lt;/strong&gt; strength.&lt;/p&gt;
&lt;p&gt;Transcribing the &lt;a href=&quot;http://en.wikipedia.org/wiki/Strong_monad&quot;&gt;definition&lt;/a&gt; from category theory into Haskell we find that a strong monad is a functor such that there exists a morphism:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;t_{A, B} : M A * B \to M (A * B)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.9012em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;with a couple of conditions on it that I'll get to later.&lt;/p&gt;
&lt;p&gt;Currying that to get something that feels more natural to a Haskell programmer we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mstrength&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; m a -&amp;gt; b -&amp;gt; m (a,b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pardo provided us with a nice definition for that in &lt;a href=&quot;http://citeseer.ist.psu.edu/pardo00towards.html&quot;&gt;Towards merging recursion and comonads&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mstrength&lt;/span&gt; ma b = ma &amp;gt;&amp;gt;= (\a -&amp;gt; return (a,b))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which we can rewrite by pulling the return out of the function:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mstrength'&lt;/span&gt; ma b = ma &amp;gt;&amp;gt;= return . (\a -&amp;gt; (a,b))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, one of the nice monad laws we have says that if your Monad is a Functor, which it &lt;a href=&quot;http://www.haskell.org/haskellwiki/Functor_hierarchy_proposal&quot;&gt;should be&lt;/a&gt;, then:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; f xs == xs &amp;gt;&amp;gt;= return . f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This law is what gives us the definition for liftM modulo the do-sugar used when writing it.&lt;/p&gt;
&lt;p&gt;This lets us write:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; f a -&amp;gt; b -&amp;gt; f (a,b)
&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt; fa b = fmap (\a -&amp;gt; (a,b)) fa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then by the monad laws any definition for Monad for this Functor must be strong in the sense that if it was made into a monad, this strength function would be a valid strength for the monad.&lt;/p&gt;
&lt;p&gt;So we get the interesting observation that all functors in Haskell are 'strong'. Lets look at a couple:&lt;/p&gt;
&lt;h2 id=&quot;example-c&quot;&gt;Example ((,)c)&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((,)c) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f ~(a,b) = (a,f b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above may be familiar as the reader comonad, or as the functor induced by the (,) Bifunctor.&lt;/p&gt;
&lt;p&gt;What is the meaning of its strength?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt;{(,)c} :: ((c,a),b) -&amp;gt; (c,(a,b))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well, thats just the associative law for the (,) bifunctor.&lt;/p&gt;
&lt;h2 id=&quot;example-either-a&quot;&gt;Example (Either a)&lt;/h2&gt;
&lt;p&gt;What about the built-in functor instance for (Either a)?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; b) = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; (f b)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;strength&lt;/span&gt;{&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c} :: (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c a, b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c (a,b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This strength gives us a (slightly weak) form of distributive law for sums over products in Haskell.&lt;/p&gt;
&lt;p&gt;Having strength lets us know that if we have a functor of a's I can go through it and just drop in b's in along side each of the a's.&lt;/p&gt;
&lt;p&gt;The show is over. Everyone can go home.&lt;/p&gt;
&lt;p&gt;Not &lt;em&gt;quite&lt;/em&gt;. What about comonadic &lt;strong&gt;costrength&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;s_{A,B} : W (A + B) \to W A + B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7167em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0502em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;with a couple of laws we can ignore for the moment.&lt;/p&gt;
&lt;p&gt;Since we can derive strength for all Functors in Haskell, we'd think at first&lt;br&gt;
that we could do the same for costrength, after all most constructions work out that way when you can&lt;br&gt;
construct one, its dual usually means something interesting and works out fine.&lt;/p&gt;
&lt;p&gt;Here I'll introduce a typeclass, foreshadowing that this probably won't go so smoothly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Costrong&lt;/span&gt; w &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  costrength :: w (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (w a) b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately costrength cannot be derived for every functor in Haskell. Lets look at what it does and see why.&lt;/p&gt;
&lt;p&gt;With costrength, given a data structure decorated at each point with either an 'a' or a 'b' I can walk the entire structure and if I found a's everywhere then I know I have 'a's in every position, so I can strengthen the type to say that it just contains 'a's. Otherwise I found a b, so I'll give you one of the b's I found. This requires that I'm somehow able to decide if the structure contains b's anywhere and constructively give you one if it does.&lt;/p&gt;
&lt;p&gt;Lets find a functor that you can't do this to.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((-&amp;gt;)e) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
   fmap  = (.)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An instance of costrength for (-&amp;gt;) e,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt;{(-&amp;gt;)e} :: (e -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (e -&amp;gt; a) b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;would be equivalent to deciding that the function returns only Left's for all inputs.&lt;/p&gt;
&lt;p&gt;Epic failure; functions are out.&lt;/p&gt;
&lt;p&gt;Now, if we restrict ourselves to polynomial functors, we can try again, but what about infinite data structures?&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a = a &amp;lt; : &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets define the following stream comparison function:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;eqstream&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Eq&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; () ())
&lt;span class=&quot;hljs-title&quot;&gt;eqstream&lt;/span&gt; (a &amp;lt; : &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) (b &amp;lt;: bs) = c &amp;lt;: eqstream &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; bs &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  c = &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; a == b &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; () &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://fsl.cs.uiuc.edu/pubs/rosu-2006-icfp.pdf&quot;&gt;Deciding equality of streams&lt;/a&gt; is &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Π&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msubsup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\Pi_0^2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.0622em;vertical-align:-0.2481em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;Π&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-2.4519em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2481em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; complete , so this would imply that we have an oracle for the halting problem!&lt;/p&gt;
&lt;p&gt;Ok, so infinite data structures are out.&lt;/p&gt;
&lt;p&gt;This rules out 'coinductive' structures in general, but inductive structures are fine.&lt;/p&gt;
&lt;p&gt;So what is in?&lt;/p&gt;
&lt;p&gt;In Scheme you can define costrength with the use of call-cc, which I'll leave as an exercise to the reader.&lt;/p&gt;
&lt;p&gt;But, you can't use fmap to do that in Haskell, because call-cc passing around the current continuation is a form of monadic side effect. You could use the old Data.FunctorM and a Cont monad, but we like to think in terms of Data.Traversable today.&lt;/p&gt;
&lt;p&gt;Unfortunately 'Either' isn't a Haskell monad in general because of some noise about trying to support 'fail', but if we define a less restrictive Either monad than the one in Control.Monad.Error, like the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a
  &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a &amp;gt;&amp;gt;= k = k a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then using the version of mapM in Data.Traversable,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mapM&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; t, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt; (a -&amp;gt; m b) -&amp;gt; t a -&amp;gt; m (t b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;if we look at this specialized to 'id',&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;mapM&lt;/span&gt;{&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a}  id :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; f =&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a (f b)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we have almost has the right type. (In fact the above is probably a more natural signature for costrength in Haskell, because it is a distributive law for any Traversable functor f over (Either a). In fact mapM id (also known as sequence) is a distributive law for a traversable functor over any monad.&lt;/p&gt;
&lt;p&gt;If we note the fact that sums are symmetric:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Symmetric&lt;/span&gt; p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
     swap :: p a b -&amp;gt; p b a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Symmetric&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    swap (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a
    swap (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Traversable&lt;/span&gt; f =&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (f a) b
&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt; = swap . mapM swap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The ability to define strength in general came from the fact that we were lazy enough that 'strength' doesn't try to evaluate the potentially infinite structure (there are little hidden functions all over the place in the form of thunks). The trade off is that we aren't 'strict' enough for 'costrength' to be definable in general.&lt;/p&gt;
&lt;p&gt;A couple of uses for costrength:&lt;/p&gt;
&lt;h2 id=&quot;example-either-c&quot;&gt;Example (Either c)&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt; {&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c} :: &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; c a) b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is just the coassociative law for Either.&lt;/p&gt;
&lt;h2 id=&quot;example-c-2&quot;&gt;Example ((,)c)&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt; {(,)c} :: (c, &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (c,a) b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;lets us distribute sums over products another way.&lt;/p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example []&lt;/h2&gt;
&lt;p&gt;Finally,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;costrength&lt;/span&gt; {[]} :: [&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; a b] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; [a] b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;lets us pretend that we can solve the stream problem above, but it just bottoms out if you apply it to an infinite list.&lt;/p&gt;
&lt;p&gt;In short, in Haskell, every Functor is strong and every Traversable Functor is (something like) costrong.&lt;/p&gt;
&lt;p&gt;[Edit: Dan Doel pointed out that instead of mapM id you could use sequence]&lt;/p&gt;
&lt;p&gt;[Edit: @blaisorblade pointed out that this should really be using traverse these days]&lt;/p&gt;
&lt;p&gt;[Edit: This isn't quite costrength. Why? It fails the reverse of the second strength law. In reality we need to limit ourselves further -- to left adjoints.]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/deriving-strength-from-laziness/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>The Cofree Comonad and the Expression Problem</title><link>https://comonad.com/reader/2008/the-cofree-comonad-and-the-expression-problem/</link><guid isPermaLink="false">https://comonad.com/reader/2008/the-cofree-comonad-and-the-expression-problem/</guid><pubDate>Wed, 30 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 April 2008&lt;/p&gt;&lt;span id=&quot;more-53&quot;&gt;&lt;/span&gt;&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Identity
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Arrow ((&amp;amp;&amp;amp;&amp;amp;), (***),(+++), (|||))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to talk about duality briefly. I don't want to go all the way to &lt;a href=&quot;http://citeseer.ist.psu.edu/filinski89declarative.html&quot;&gt;Filinski&lt;/a&gt;-style or &lt;a href=&quot;http://research.microsoft.com/users/simonpj/papers/not-not-ml/index.htm&quot;&gt;Haskell is Not Not ML&lt;/a&gt;-style value/continuation duality, but I do want to poke a bit at the variant/record duality explified by the extensible cases used to handle variants in &lt;a href=&quot;http://ttic.uchicago.edu/~wchae/wiki/pmwiki.php&quot;&gt;MLPolyR&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The need for extensible cases to handle open variants is part of the expression problem as stated by Wadler:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One obvious trick is to use an extensible record of functions as a 'case' statement, with each field corresponding to one of the variants. To index into records you can use an extensible variant of functions to represent a field selection. In a purer form ala the Filinski or the Haskell is Not Not ML approach mentioned above, you can replace the word 'function' with continuation and everything works out.&lt;/p&gt;
&lt;p&gt;Sweirstra recently tackled the extensible variant side of the equation with in &lt;a href=&quot;http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf&quot;&gt;Data types a la carte&lt;/a&gt; using the free monad coproduct to handle the 'variant' side of things, leaving the handling of cases to typeclasses, but we can see if we can go one better and just exploit the variant/record duality directly.&lt;/p&gt;
&lt;h2 id=&quot;fight-club-for-functors&quot;&gt;Fight Club for Functors&lt;/h2&gt;
&lt;p&gt;Leaning a little on multi-parameter type classes we define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; f g | f -&amp;gt; g, g -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap :: (a -&amp;gt; b -&amp;gt; c) -&amp;gt; f a -&amp;gt; g b -&amp;gt; c

(&amp;gt;$&amp;lt; ) :: &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; f g =&amp;gt; f (a -&amp;gt; b) -&amp;gt; g a -&amp;gt; b
(&amp;gt;$&amp;lt; ) = zap id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The (&amp;gt;$&amp;lt;) operator takes a functor containing functions, and its 'dual functor' and annihilates them both obtaining a single value in a deterministic fashion.&lt;/p&gt;
&lt;p&gt;The easiest inhabitant of this typeclass is the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap f (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a) (&lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; b) = f a b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After all there is only one item to be had on both the left and right so the choice is obvious. Now, we can take a couple of additional functors, the coproduct and product functors and define instances of Dual for them:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) a = &lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :*: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) a = &lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; (fmap f x)
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; y) = &lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; (fmap f y)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; x y) = &lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; (fmap f x) (fmap f y)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt; :*: &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; f) (&lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; a _) = zap op f a
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; f) (&lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; _ b) = zap op f b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :*: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) (&lt;span class=&quot;hljs-title&quot;&gt;f'&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g'&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; f _) (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; a) = zap op f a
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Prod&lt;/span&gt; _ g) (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; b) = zap op g b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can use the above to define an extensible case using (:*:)'s to handle any matching variant (:+:).&lt;/p&gt;
&lt;p&gt;Clearly if you use any composition of the above, what will happen is whenever you have a product on the left you will have a sum on the right 'choosing' which half of the product you are interested, and whenever you have a sum on the left you will have a product on the right, and the sum in THAT case will choose which half of the product you are interested in. You will eventually reach a leaf (or evaluate to bottom), and the only base case we have is the Identity functor on both sides, so you will have only one candidate value to return.&lt;/p&gt;
&lt;p&gt;The 'dispatch' of the function call is handled by some choices being made by sums on the left and others being made by sums on the right, but always in order to preserve duality, there is a corresponding pair of options on the other side.&lt;/p&gt;
&lt;p&gt;A more straightforward insight might be obtained by extending this logic to bifunctors to eliminate some of the noise and allow your types to vary more.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | Bifunctor Duality&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BiDual&lt;/span&gt; p q | p -&amp;gt; q, q -&amp;gt; p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizap :: (a -&amp;gt; c -&amp;gt; e) -&amp;gt; (b -&amp;gt; d -&amp;gt; e) -&amp;gt; p a b -&amp;gt; q c d -&amp;gt; e

(&amp;gt;&amp;gt;$&amp;lt; &amp;lt;):: &lt;span class=&quot;hljs-type&quot;&gt;BiDual&lt;/span&gt; p q =&amp;gt; p (a -&amp;gt; c) (b -&amp;gt; c) -&amp;gt; q a b -&amp;gt; c
(&amp;gt;&amp;gt;$&amp;lt; &amp;lt;) = bizap id id
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BiDual&lt;/span&gt; (,) &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizap l r (f,g) (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; a)  = l f a
  bizap l r (f,g) (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; b) = r g b
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BiDual&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; (,) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bizap l r (&lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; f) (a,b)  = l f a
  bizap l r (&lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt; g) (a,b) = r g b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the latter definition in hand, we can use products of functions to annihilate sums of values, or sums of functions to annihilate products of values.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ten&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ten&lt;/span&gt; = ((*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;),id) &amp;gt;&amp;gt;$&amp;lt; &amp;lt; &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;four&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;four&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt; (/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) &amp;gt;&amp;gt;$&amp;lt; &amp;lt; (&lt;span class=&quot;hljs-number&quot;&gt;8.0&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;True&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use the earlier definitions to define the different algebra instances used by Swierstra as functions as a product of functions thereby decoupling us from the typeclass machinery.&lt;/p&gt;
&lt;p&gt;I'll leave this bit as an exercise for the reader. The translation is pretty much straightforward.&lt;/p&gt;
&lt;p&gt;[Edit: See a simple worked example in the comments]&lt;/p&gt;
&lt;p&gt;&lt;em&gt;However&lt;/em&gt;, the catamorphism used in the a la Carte paper to deconstruct the free monad with an initial algebra is not the only way you may want to take a free monad apart!&lt;/p&gt;
&lt;p&gt;We can also use the cofree comonad of its dual functor, exploiting the same duality we used above to construct the algebra itself. And similarly we can stick a bunch of functions in the free monad of a the dual of a functor to pick a value out of a cofree comonad.&lt;/p&gt;
&lt;p&gt;Where the a la Carte paper approach let you carry around different variants, the cofree comonad product construction allows you to 'carry around more stuff in each one.' The record/variant stuff has been around since Oleg et al.'s &lt;a href=&quot;http://darcs.haskell.org/HList/&quot;&gt;HList&lt;/a&gt;/&lt;a href=&quot;http://homepages.cwi.nl/~ralf/OOHaskell/&quot;&gt;OOHaskell&lt;/a&gt; stuff, but I don't recall seeing records of functions used to handle variants in that setting. I'm sure someone will correct me with a 15 year old example.&lt;/p&gt;
&lt;p&gt;Recall the relevant portions of the free monad and cofree comonad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runCofree&lt;/span&gt; :: (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runFree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; . (f *** fmap (fmap f)) . runCofree
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; . (f +++ fmap (fmap f)) . runFree

&lt;span class=&quot;hljs-title&quot;&gt;anaC&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;anaC&lt;/span&gt; t = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; . (id &amp;amp;&amp;amp;&amp;amp; fmap (anaC t) . t)
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Left&lt;/span&gt;
  m &amp;gt;&amp;gt;= k = (k ||| (inFree . fmap (&amp;gt;&amp;gt;= k))) (runFree m)

&lt;span class=&quot;hljs-title&quot;&gt;inFree&lt;/span&gt; :: f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a
&lt;span class=&quot;hljs-title&quot;&gt;inFree&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can use the bizap we defined above for bifunctors to handle the (,) and Either portions and the zap function defined above to handle the nested functor, obtaining:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; fs) (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = bizap op (zap (zap op)) fs &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; f g =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Dual&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  zap op (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; fs) (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;) = bizap op (zap (zap op)) fs &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The most trivial example of a free monad and a cofree comonad would be the 'natural number' free monad and the 'stream' comonad, which both coincidentally can be obtained from the Identity functor -- how convenient! Its almost like I planned this.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define a successor function for our Naturals:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;suck&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nat&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;suck&lt;/span&gt; = inFree . &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can build up a stream of integers, just to have a stream to search through:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;ints&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Stream&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;ints&lt;/span&gt; = anaC (return . (+&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can look at the &lt;em&gt;n&lt;/em&gt;th element of the stream, by annihilating it with a free monad of the dual of its base functor.&lt;/p&gt;
&lt;p&gt;In other words, we can ask for the element at a position that is given as a natural number!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;two&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;two&lt;/span&gt; = suck (suck (return id)) &amp;gt;$&amp;lt; ints
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And by duality we can take a stream of functions, and use it to annihilate a Nat functor wrapped around a value. Another exercise for the reader.&lt;/p&gt;
&lt;p&gt;These are of course the simplest example of a free monad and a cofree comonad, but it works for any dualizable construction.&lt;/p&gt;
&lt;p&gt;i.e. Given a binary tree containing values you index with a path into the tree. If your tree is potentially non-infinite then your path has to be decorated with functions in order to handle potential leaves. If your path is non-infinite then your tree has to be decorated with values. The types enforce that you'll either return bottom or find a single value at some point.&lt;/p&gt;
&lt;p&gt;Two functors enter, one value leaves.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/posts/FreeExpression.hs&quot;&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/the-cofree-comonad-and-the-expression-problem/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Dynamorphisms as Chronomorphisms</title><link>https://comonad.com/reader/2008/dynamorphisms-as-chronomorphisms/</link><guid isPermaLink="false">https://comonad.com/reader/2008/dynamorphisms-as-chronomorphisms/</guid><pubDate>Sat, 26 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 April 2008&lt;/p&gt;&lt;span id=&quot;more-51&quot;&gt;&lt;/span&gt;&lt;p&gt;In case it wasn't obvious, I thought I should mention that Kabanov and Vene's &lt;a href=&quot;http://citeseer.ist.psu.edu/748315.html&quot;&gt;dynamorphisms&lt;/a&gt; which optimize histomorphisms for dynamic programming can be expressed readily as &lt;a href=&quot;https://comonad.com/reader/2008/time-for-chronomorphisms/&quot;&gt;chronomorphisms&lt;/a&gt;; they just use an &lt;a href=&quot;http://en.wikipedia.org/wiki/Anamorphism&quot;&gt;anamorphism&lt;/a&gt; instead of a &lt;a href=&quot;http://www.mii.lt/informatica/pdf/INFO141.pdf&quot;&gt;futumorphism&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- | dynamorphism&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;dyna&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
  (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f b) -&amp;gt; b) -&amp;gt;
  (a -&amp;gt; f a) -&amp;gt;
  (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;dyna&lt;/span&gt; f g = extract . dyna' f g

&lt;span class=&quot;hljs-comment&quot;&gt;-- | dynamorphism kernel&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;dyna'&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
  (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f b) -&amp;gt; b) -&amp;gt;
  (a -&amp;gt; f a) -&amp;gt;
  (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f b)
&lt;span class=&quot;hljs-comment&quot;&gt;--dyna' f g = hylo (Cofree . (f &amp;amp;&amp;amp;&amp;amp; id)) g&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;dyna'&lt;/span&gt; f g = chrono' f (fmap return . g) . return

&lt;span class=&quot;hljs-comment&quot;&gt;-- | generalized dynamorphism&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;g_dyna&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; h) =&amp;gt;
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. f (h b) -&amp;gt; h (f b)) -&amp;gt;
  (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; h b) -&amp;gt; b) -&amp;gt;
  (a -&amp;gt; f a) -&amp;gt;
  (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;g_dyna&lt;/span&gt; k f g = extract . g_dyna' k f g

&lt;span class=&quot;hljs-comment&quot;&gt;-- | generalized dynamorphism kernel&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;g_dyna'&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; h) =&amp;gt;
  (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. f (h b) -&amp;gt; h (f b)) -&amp;gt;
  (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; h b) -&amp;gt; b) -&amp;gt;
  (a -&amp;gt; f a) -&amp;gt;
  (a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; h b)
&lt;span class=&quot;hljs-title&quot;&gt;g_dyna'&lt;/span&gt; k f g = g_chrono' k id f (fmap return . g) . return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moreover, as an interesting aside, since one side is an anamorphism, there is no power to be gained for a dynamorphism by &lt;a href=&quot;https://comonad.com/reader/2008/unnatural-transformations/&quot;&gt;introducing a natural transformation&lt;/a&gt; term, even though dynamorphism is a form of chronomorphism, because 'eta' can be folded into the anamorphism side of the chronomorphism, as you do with a normal hylomorphism.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/Chronomorphism.hs&quot;&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/dynamorphisms-as-chronomorphisms/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Time for Chronomorphisms</title><link>https://comonad.com/reader/2008/time-for-chronomorphisms/</link><guid isPermaLink="false">https://comonad.com/reader/2008/time-for-chronomorphisms/</guid><pubDate>Sat, 26 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 April 2008&lt;/p&gt;&lt;p&gt;First, we can make the &lt;a href=&quot;https://comonad.com/reader/2008/generalized-hylomorphisms/&quot;&gt;generalized hylomorphism&lt;/a&gt; from the other day more efficient by noting that once you inline the &lt;a href=&quot;http://en.wikipedia.org/wiki/Hylomorphism_(computer_science)&quot;&gt;hylomorphism&lt;/a&gt;, you can see that you do 3 fmaps over the same structure, so we can fuse those together yielding:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (f a)) -&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (f a) -&amp;gt; f (m a)) -&amp;gt;
          (f (w b) -&amp;gt; b) -&amp;gt;
          (a -&amp;gt; f (m a)) -&amp;gt;
          (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; w m f g = extract . g_hylo' w m f g . return

&lt;span class=&quot;hljs-comment&quot;&gt;-- | the kernel of the generalized hylomorphism&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (f a)) -&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (f a) -&amp;gt; f (m a)) -&amp;gt;
          (f (w b) -&amp;gt; b) -&amp;gt;
          (a -&amp;gt; f (m a)) -&amp;gt;
          (m a -&amp;gt; w b)
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'&lt;/span&gt; w m f g =
    liftW f . w .
    fmap (duplicate . g_hylo' w m f g . join) .
    m . liftM g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, the above made me realize that most of the generalized cata/ana, etc morphisms give you a little more interesting stuff to do if you separate out the recursive part. Then you can pass it a monad built with something other than return to perform substitution on, or inspect the comonadic wrapper on the result.&lt;/p&gt;
&lt;p&gt;Oh, and to support my earlier claim that g_hylo generalizes g_cata and g_ana here are derivations of each in terms of g_hylo.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w) =&amp;gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (f a)) -&amp;gt;
    (f (w a) -&amp;gt; a) -&amp;gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Mu&lt;/span&gt; f -&amp;gt; a

&lt;span class=&quot;hljs-title&quot;&gt;g_cata&lt;/span&gt; k f = g_hylo k (fmap &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; . runId) f (fmap &lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; . outF)

&lt;span class=&quot;hljs-title&quot;&gt;g_ana&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
   (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (f a) -&amp;gt; f (m a)) -&amp;gt;
   (a -&amp;gt; f (m a)) -&amp;gt;
   a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;g_ana&lt;/span&gt; k g = g_hylo (&lt;span class=&quot;hljs-type&quot;&gt;Id&lt;/span&gt; . fmap runId) k (&lt;span class=&quot;hljs-type&quot;&gt;InF&lt;/span&gt; . fmap runId) g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an aside, histomorphisms have a dual that seems to be elided from most lists of recursion schemes: &lt;a href=&quot;http://www.mii.lt/informatica/pdf/INFO141.pdf&quot;&gt;Uustalu and Vene&lt;/a&gt; call it a futumorphism. It basically lets you return a structure with seeds multiple levels deep rather than have to plumb 'one level at a time' through the anamorphism. While a histomorphism is a generalized catamorphism parameterized by the cofree comonad of your functor, a futumorphism is a generalized anamorphism parameterized by the free monad of your functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;futu&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a)) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;futu&lt;/span&gt; f = ana ((f ||| id) . runFree) . return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, g_hylo is painfully general, so lets look at a particularly interesting choice of comonad and monad for a given functor that always have a distributive law: the cofree comonad, and the free monad of that very same functor!&lt;/p&gt;
&lt;p&gt;This gives rise to a particular form of morphism that I haven't seem talked about in literature, which after kicking a few names around on the haskell channel we chose to call a &lt;strong&gt;chronomorphism&lt;/strong&gt; because it subsumes histo- and futu- morphisms.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;chrono&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
    (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; f b) -&amp;gt; b) -&amp;gt;
    (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a)) -&amp;gt;
    a -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unlike most of the types of these generalized recursion schemes, chrono's type is quite readable!&lt;/p&gt;
&lt;p&gt;A chronomorphism's fold operation can 'look back' at the results it has given, and its unfold operation can 'jump forward' by returning seeds nested multiple levels deep. It relies on the fact that you always have a distributive law for the cofree comonad of your functor over the functor itself and also one for the functor over its free monad and so it works for any Functor.&lt;/p&gt;
&lt;p&gt;You can generalize it like you generalize histomorphisms and futumorphisms, and derive ana and catamorphisms from it by noting the fact that you can fmap extract or fmap return to deal with the cofree comonad or free monad parts of the term.&lt;/p&gt;
&lt;p&gt;Alternately, since the 'identity comonad' can be viewed as the cofree comonad of the &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;⊥&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\perp&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊥&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; Functor that maps everything to &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;⊥&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\perp&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊥&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, you can also choose to rederive generalized futumorphisms from generalized chronomorphism using the distributive law of the identity comonad.&lt;/p&gt;
&lt;p&gt;Below you'll find source code for generalized hylo- cata- ana- histo- futu- chrono- etc... morphisms and their separated kernels.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/Chronomorphism.hs&quot;&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As an aside, Dan Doel (dolio) has started packaging these up for addition to category-extras in Hackage.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/time-for-chronomorphisms/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Unnatural Transformations</title><link>https://comonad.com/reader/2008/unnatural-transformations/</link><guid isPermaLink="false">https://comonad.com/reader/2008/unnatural-transformations/</guid><pubDate>Sat, 26 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 April 2008&lt;/p&gt;&lt;span id=&quot;more-50&quot;&gt;&lt;/span&gt;&lt;p&gt;Back in the days of &lt;a href=&quot;http://citeseer.ist.psu.edu/41091.html&quot;&gt;HYLO&lt;/a&gt;, it was common to write hylomorphisms with an additional natural transformation in them. Well, I was still coding in evil imperative languages back then, but I have it on reliable, er.. well supposition, that this is probably the case, or at least that they liked to do it back in the HYLO papers anyways.&lt;/p&gt;
&lt;p&gt;Transcoding the category theory mumbo-jumbo into Haskell, so I can have a larger audience, we get the following 'frat combinator' -- you can blame Jules Bean from #haskell for that.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;hyloEta&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt;
     (g b -&amp;gt; b) -&amp;gt;
     (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f a -&amp;gt; g a) -&amp;gt;
     (a -&amp;gt; f a)
&lt;span class=&quot;hljs-title&quot;&gt;hyloEta&lt;/span&gt; phi eta psi = phi . eta . fmap (hyloEta phi eta psi) . psi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We placed eta in the middle of the argument list because it is evocative of the fact that it occurs between phi and psi, and because that seems to be where everyone else puts it.&lt;/p&gt;
&lt;p&gt;Now, clearly, we could roll eta into phi and get the more traditional hylo where f = g. Less obviously we could roll it into psi because it is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Natural_transformation&quot;&gt;natural transformation&lt;/a&gt; and so the following diagram commutes:&lt;/p&gt;
&lt;figure class=&quot;category-diagram&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/unnatural-square.svg&quot; alt=&quot;F(A), F(B), G(A), G(B); F⟦f, g⟧, ηₐ, ηᵦ, G⟦f, g⟧&quot;&gt;&lt;/figure&gt;
&lt;p&gt;This 'Hylo Shift' property (mentioned in that same paper) allows us to move the 'eta' term into the phi term or into the psi term as we see fit. Since we can move the eta term around and it adds no value to the combinator, it quietly returned to the void from whence it came. hyloEta offers us no more power than hylo, so out it goes.&lt;/p&gt;
&lt;p&gt;So, if its dead, why talk about it?&lt;/p&gt;
&lt;p&gt;Well, when we move to a generalized hylomorphism we have a design decision that has some performance effects, and my initial pass at a generalized hylomorphism isn't as general as it could be. When we open up the generalized hylomorphism and look at its guts (check the slightly updated &lt;a href=&quot;https://comonad.com/haskell/Chronomorphism.hs&quot;&gt;source code&lt;/a&gt; from yesterday) we see:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'&lt;/span&gt; w m f g = liftW f . w . fmap duplicate . fmap (g_hylo' w m f g) . fmap join . m . liftM g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;expanding that to include the eta term gives us 4 candidate locations where we can abuse its status as a natural transformation to slot it in.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'1&lt;/span&gt; w m f eta g =
    liftW f .
    w . eta . fmap duplicate . fmap (g_hylo' w m f g) . fmap join . m .
    liftM g
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'2&lt;/span&gt; w m f eta g =
    liftW f .
    w . fmap duplicate . eta . fmap (g_hylo' w m f g) . fmap join . m .
    liftM g
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'3&lt;/span&gt; w m f eta g =
    liftW f .
    w . fmap duplicate . fmap (g_hylo' w m f g) . eta . fmap join . m .
    liftM g
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'4&lt;/span&gt; w m f eta g =
    liftW f .
    w . fmap duplicate . fmap (g_hylo' w m f g) . fmap join . eta . m .
    liftM g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;g-hylo'1 and g_hylo'4 are particularly interesting because we have functions sitting right next to them that we can fuse it into by generalizing the type signatures only slightly and because that leaves a run of 3 fmaps in a row that we can fuse together. If we generalize the signatures of both w and m we get the following definition that allows you to place it on the left or the right, and for g_hylo to not have to care about it.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- new and improved!&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (g a)) -&amp;gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (e a) -&amp;gt; f (m a)) -&amp;gt;
    (g (w b) -&amp;gt; b) -&amp;gt;
    (a -&amp;gt; e (m a)) -&amp;gt;
    (a -&amp;gt; b)
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; w m f g = extract . g_hylo' w m f g . return

&lt;span class=&quot;hljs-comment&quot;&gt;-- | the kernel of the generalized hylomorphism&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
     (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (g a)) -&amp;gt;
     (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (e a) -&amp;gt; f (m a)) -&amp;gt;
     (g (w b) -&amp;gt; b) -&amp;gt;
     (a -&amp;gt; e (m a)) -&amp;gt;
     (m a -&amp;gt; w b)
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo'&lt;/span&gt; w m f g = liftW f . w . fmap (duplicate . g_hylo' w m f g . join) . m . liftM g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The slightly generalized signatures for our two distributive laws now allow them to change functors on the way through, but we shed a superfluous argument.&lt;/p&gt;
&lt;p&gt;Note that while 3 'Functors' e, f and g are involved, only f needs to be a Functor in Hask because we do the duplication, hylomorphism and join all inside f in either case. And most of the time e = f = g. For instance e or g could be &lt;a href=&quot;https://comonad.com/reader/2008/rotten-bananas/&quot;&gt;exponential&lt;/a&gt; or &lt;a href=&quot;http://mathworld.wolfram.com/ContravariantFunctor.html&quot;&gt;contravariant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So now that we've generalized our generalized hylomorphism we're done right?&lt;/p&gt;
&lt;p&gt;Not quite. Unfortunately the same trick doesn't work for the &lt;a href=&quot;https://comonad.com/reader/2008/time-for-chronomorphisms/&quot;&gt;generalized chronomorphism&lt;/a&gt; defined last night.&lt;/p&gt;
&lt;p&gt;To see why, we have open up chrono and peek at its guts.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;chrono&lt;/span&gt; = g_chrono id id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well, that was boring. Digging deeper we find:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_chrono&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; g, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w) =&amp;gt;
      (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. f (w b) -&amp;gt; w (f b)) -&amp;gt;
      (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. m (f b) -&amp;gt; f (m b)) -&amp;gt;
      (f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; w b) -&amp;gt; b) -&amp;gt;
      (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; m a)) -&amp;gt;
      a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;g_chrono&lt;/span&gt; w m = g_hylo (distCofree w) (distFree m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sticking in hylo's vestigial natural transformation, we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;g_chronoEta&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; g, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; m, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w) =&amp;gt;
      (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. g (w b) -&amp;gt; w (g b)) -&amp;gt;
      (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; b. m (f b) -&amp;gt; f (m b)) -&amp;gt;
      (g (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; w b) -&amp;gt; b) -&amp;gt;
      (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; c. f a -&amp;gt; g a) -&amp;gt;
      (a -&amp;gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; m a)) -&amp;gt;
      a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;g_chronoEta&lt;/span&gt; w m f eta g = g_hylo (distCofree w . eta) (distFree m) f g
&lt;span class=&quot;hljs-comment&quot;&gt;-- g_chronoEta w m f eta g = g_hylo (distCofree w) (eta . distFree m) f g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And so, we roll up our sleeves ready to merge it into something, be it f, g, w, m, anything, but it seems the only places eta can go is to merge into one of the distributive laws, because f and g are executed lifted.&lt;/p&gt;
&lt;p&gt;Unfortunately, the user passed us rules for distributing the base functor of the cofree comonad and free monad, not for distributing the whole cofree comonad. And my efforts to generalize distFree and distCofree have thus far met with some frustration, there isn't much to grab onto there to write the more general signature.&lt;/p&gt;
&lt;p&gt;Ideally, I'd just be able to merge it into one of the distributive laws. Since the HYLO guys liked to put it on the left of the recursive call to the hylomorphism, we'll look at distCofree. The desired signature for distCofree' would be:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;distCofree'&lt;/span&gt; ::   (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; g, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; h) =&amp;gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (h a) -&amp;gt; h (g a)) -&amp;gt;
    f (&lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; h a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cofree&lt;/span&gt; h (g a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it should have the property that:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;distCofree'&lt;/span&gt; (f . eta) == distCofree' f . eta
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without that, g_chronoEta is more powerful than g_chrono. Naturally.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/Chronomorphism.hs&quot;&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/unnatural-transformations/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Generalized Hylomorphisms</title><link>https://comonad.com/reader/2008/generalized-hylomorphisms/</link><guid isPermaLink="false">https://comonad.com/reader/2008/generalized-hylomorphisms/</guid><pubDate>Thu, 24 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 24 April 2008&lt;/p&gt;&lt;p&gt;I haven't seen written up anywhere the following operator (g_hylo), defined in the spirit of generalized catamorphisms and generalized anamorphisms, which seems to follow rather naturally from the definition of both -- I'm using liftW &amp;amp; liftM rather than fmap to make it clear what is being lifted over what.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; w =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;hljs-comment&quot;&gt;-- minimal definition: extend &amp;amp; extract or duplicate &amp;amp; extract&lt;/span&gt;
        duplicate :: w a -&amp;gt; w (w a)
        extend :: (w a -&amp;gt; b) -&amp;gt; w a -&amp;gt; w b
        extract :: w a -&amp;gt; a
        extend f = fmap f . duplicate
        duplicate = extend id

&lt;span class=&quot;hljs-title&quot;&gt;liftW&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w =&amp;gt; (a -&amp;gt; b) -&amp;gt; w a -&amp;gt; w b
&lt;span class=&quot;hljs-title&quot;&gt;liftW&lt;/span&gt; f = extend (f . extract)

&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt; w, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m) =&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. f (w a) -&amp;gt; w (f a)) -&amp;gt;
          (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. m (f a) -&amp;gt; f (m a)) -&amp;gt;
          (f (w b) -&amp;gt; b) -&amp;gt;
          (a -&amp;gt; f (m a)) -&amp;gt;
          a -&amp;gt; b
&lt;span class=&quot;hljs-title&quot;&gt;g_hylo&lt;/span&gt; w m f g =
     extract .
     hylo (liftW f . w . fmap duplicate) (fmap join . m . liftM g)
     . return
   &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
     hylo f g = f . fmap (hylo f g) . g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above, w and m are the distributive laws for the comonad and monad respectively, and hylo is a standard hylomorphism. In the style of &lt;a href=&quot;http://www.eyrie.org/~zednenem/&quot;&gt;Dave Menendez&lt;/a&gt;'s &lt;a href=&quot;http://www.eyrie.org/~zednenem/2004/hsce/Control.Recursion.html&quot;&gt;Control.Recursion&lt;/a&gt; code it would be a 'refoldWith' and it can rederive a whole lot of recursion and corecursion patterns if not all of them.&lt;/p&gt;
&lt;p&gt;Anyone?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/generalized-hylomorphisms/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Monads for Free</title><link>https://comonad.com/reader/2008/monads-for-free/</link><guid isPermaLink="false">https://comonad.com/reader/2008/monads-for-free/</guid><pubDate>Fri, 11 Apr 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 11 April 2008&lt;/p&gt;&lt;span id=&quot;more-46&quot;&gt;&lt;/span&gt;&lt;p&gt;Today I'd like to talk about free monads.&lt;/p&gt;
&lt;p&gt;The free monad of a functor is a monad that is uniquely determined by the functor (up to isomorphism, etc), given by:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) | &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; a&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;-- newtype Free f a = Free { unfree :: Either a (f (Free f a))) }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usually the above is written up using a newtype around a sum (Either) so you can write it using nice point-free style, but I think this makes for clearer introduction this way.&lt;/p&gt;
&lt;p&gt;The idea is that you take the functor and recursively fold it in upon a choice of either itself or a naked variable.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; $ fmap (fmap f) x
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; (f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we wouldn't call it the free 'monad' without reason. Return is the obvious candidate for 'return', but bind is a little trickier:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  return = &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; m &amp;gt;&amp;gt;= k = k m &lt;span class=&quot;hljs-comment&quot;&gt;-- given by: return m &amp;gt;&amp;gt;= k = k m&lt;/span&gt;
  &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; m &amp;gt;&amp;gt;= k = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; $ fmap (&amp;gt;&amp;gt;= k) m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&amp;gt;&amp;gt;=) substitutes 'subtrees' for all of the naked variables in our monad. This is the gist of the monads of (co)trees section of Uustalu and Vene's &lt;a href=&quot;http://citeseer.ist.psu.edu/uustalu02dual.html&quot;&gt;The Dual of Substitution is Redecoration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can define a form of catamorphism for the free monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;foldF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;foldF&lt;/span&gt; phi (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = phi $ fmap (foldF phi) x
&lt;span class=&quot;hljs-title&quot;&gt;foldF&lt;/span&gt; _ (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is you want to be able to perform different folds that return different types, so lets quantify over the variable in the monad.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unforall&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;cataF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cataF&lt;/span&gt; phi = foldF phi . unforall
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets motivate this with an example. Take the identity functor, and give it a funny name:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; a) = &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can steal a nice typeclass from Laemmel and Rypacek:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  show (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = &lt;span class=&quot;hljs-string&quot;&gt;&quot;(Roll (&quot;&lt;/span&gt; ++ show x ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;))&quot;&lt;/span&gt;
  show (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x) = &lt;span class=&quot;hljs-string&quot;&gt;&quot;(Return (&quot;&lt;/span&gt; ++ show x ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;))&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with it we can see that the members of the monad &quot;Free Succ&quot; are terms of the form:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x
&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x))
&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x))))
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which if we look through it with goggles that quantify over x and ignore the Return/Roll noise looks like the Peano numerals!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Peano&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then working in the monad &quot;Free Succ&quot;, the bind function (&amp;gt;&amp;gt;=) hunts down the value of the 'a' term and substitutes the&lt;br&gt;
output of the function.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; ()))) &amp;gt;&amp;gt;= const &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; ())
    == &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; ()))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can easily convert natural numbers to Peano form, exploiting this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;toNat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;toNat&lt;/span&gt; n | n &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = toNat (n - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) &amp;gt;&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;toNat&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;         = return ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can translate back from Peano form, by first replacing the () with a 0, and then using the non-polymorphic&lt;br&gt;
fold operation from before.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;toInt&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;toInt&lt;/span&gt; = foldF phi . fmap (const &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi (&lt;span class=&quot;hljs-type&quot;&gt;Succ&lt;/span&gt; n) = n + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The need to set a constant base case is common enough that we may want to box that up into a function:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata'&lt;/span&gt; :: (f a -&amp;gt; a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; f) -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cata'&lt;/span&gt; phi z =  phi $ fmap (const z) . unforall
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that example in hand you might be tempted to try the same trick with a different type: (,)&lt;/p&gt;
&lt;p&gt;First we note that (,) is a Bifunctor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap :: (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; d) -&amp;gt; f a b -&amp;gt; f c d
  first :: (a -&amp;gt; b) -&amp;gt; f a c -&amp;gt; f b c
  first f = bimap f id
  second :: (a -&amp;gt; b) -&amp;gt; f c a -&amp;gt; f c b
  second f = bimap id f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition for (,) is quite straightforward.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; (,) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  bimap f g ~(x,y) = (f x, g y)

&lt;span class=&quot;hljs-comment&quot;&gt;-- the reader comonad!&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((,)a) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (e,a) = (e,f a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ideally we would like to be able to say&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;--instance Bifunctor f =&amp;gt; Functor (f a) where fmap = second&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but this can lead to ambiguous cases in the type checker, does it look for a Bifunctor or something else? So, we'll just think that very loudly whenever we define a bifunctor.&lt;/p&gt;
&lt;p&gt;So, lets see if Free ((,)a) x can rederive the list functor. You can get pretty close:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x
&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (a, &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x)
&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (a, &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (a, &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x))
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks a lot like it, but its a different functor. The free monad &quot;Free (Cons a)&quot; varies the type of the term&lt;br&gt;
carried around in nil (aka Return) (the type of the result of applying a catamorphism). Quantifying over that gets you closer:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; ((,)a)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We had to make it a newtype in order to be able to make it an instance of monad and functor in its own right.&lt;/p&gt;
&lt;p&gt;Now, to remap the 'first' term in the bifunctor, we add a new tool to our belt:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;bimapfree&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Bifunctor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; b) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (f a) c -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Free&lt;/span&gt; (f b) c
&lt;span class=&quot;hljs-title&quot;&gt;bimapfree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; x
&lt;span class=&quot;hljs-title&quot;&gt;bimapfree&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; $ bimap f (bimapfree f) x
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; x)) = &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; $ &lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; (bimapfree f x)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;length&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; x)) = cata' phi &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; x &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi (_,b) = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; + b

&lt;span class=&quot;hljs-title&quot;&gt;sum&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;sum&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;List&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Forall&lt;/span&gt; x)) = cata' phi &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; x &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
  phi (a,b) = a + b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if you've been paying attention for the last couple of posts, you may have noticed a connection between the free monad 'Free f a' and the Fegaras/Sheard 'Rec f a':&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) | &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;They are the same construction!&lt;/p&gt;
&lt;p&gt;That said, when you have 'a' occurring in negative position in the functor (aka you have an exponential functor), then you find your hands tied in certain fundamental ways. First and foremost, the free monad fails to become a monad (well, in the category &lt;strong&gt;Hask&lt;/strong&gt;, anyways)! Secondly you lose the ability to define hylomorphisms because the result of an anamorphism can't be turned into an input for a catamorphism.&lt;/p&gt;
&lt;p&gt;More later.&lt;/p&gt;
&lt;p&gt;[Edit: corrected the definition of cataF based on an observation by Daniel James]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/monads-for-free/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Higher-Order Abstract Syntax à la Carte</title><link>https://comonad.com/reader/2008/higher-order-abstract-syntax-a-la-carte/</link><guid isPermaLink="false">https://comonad.com/reader/2008/higher-order-abstract-syntax-a-la-carte/</guid><pubDate>Wed, 26 Mar 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 March 2008&lt;/p&gt;&lt;span id=&quot;more-45&quot;&gt;&lt;/span&gt;&lt;p&gt;You may recall the definition for an exponential functor from my previous entry, which can also be viewed, I suppose, as functors in the&lt;br&gt;
category of right-invertible functions in Haskell.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xmap :: (a -&amp;gt; b) -&amp;gt; (b -&amp;gt; a) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clarifying the above, an instance of ExpFunctor should satisfy the slightly generalized version of the Functor laws from Control.Monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;xmap&lt;/span&gt; id id = id
&lt;span class=&quot;hljs-title&quot;&gt;xmap&lt;/span&gt; f g . xmap f' g' = xmap (f . f') (g' . g)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we like to apply xmap to a pair of functions such that f . g = id, as in the Fegaras/Sheard case, we get:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;xmap&lt;/span&gt; f g . xmap g f
  = xmap (f . g) (f . g) &lt;span class=&quot;hljs-comment&quot;&gt;-- by second xmap law&lt;/span&gt;
  = xmap id id                &lt;span class=&quot;hljs-comment&quot;&gt;-- by f . g = id&lt;/span&gt;
  = id                       &lt;span class=&quot;hljs-comment&quot;&gt;-- by first xmap law&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In any event, what I thought what I'd do today is note that Wouter Swierstra's &lt;a href=&quot;http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf&quot;&gt;Data Types a la Carte&lt;/a&gt; approach works over exponential functors.&lt;/p&gt;
&lt;p&gt;Swierstra's main definition looks something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) e = &lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;) | &lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; (fmap f e)
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; (fmap f e)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This permits the obvious analogue:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; (xmap f g e)
  xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; e) = &lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; (xmap f g e)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this we can quickly encode the untyped lambda calculus:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; k) = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (f . k . g)

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (f a) (f b)
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xmap = const . fmap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Even better we could define a generic Bind and Binary functors, and newtype to get Lam and App)&lt;/p&gt;
&lt;p&gt;and we can encode the recursion using any of the ways we previously established to tie the knot (Nu f, ForAll (Rec f), ForAll (Elim f)).&lt;/p&gt;
&lt;p&gt;The rest of the a la carte stuff remains unchanged.&lt;/p&gt;
&lt;p&gt;We then get a definition of catamorphism 'for free', due to the definitions from the other day.&lt;/p&gt;
&lt;p&gt;From there we can define a fairly generic pretty printing framework.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showAlgebra :: f ([&lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;) -&amp;gt; [&lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; :+: &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showAlgebra (&lt;span class=&quot;hljs-type&quot;&gt;Inl&lt;/span&gt; e) = showAlgebra e
    showAlgebra (&lt;span class=&quot;hljs-type&quot;&gt;Inr&lt;/span&gt; e) = showAlgebra e
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;), &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; f) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    show x = cata showAlgebra (runForAll x) vars
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then we can derive particular instances for the untyped lambda calculus we slapped together above:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showAlgebra (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; k) (v:vars) =
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;(\\\\&quot;&lt;/span&gt; ++ v ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;. &quot;&lt;/span&gt; ++ k (const v) vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;)&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ShowAlgebra&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    showAlgebra (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) vars =
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;(&quot;&lt;/span&gt; ++ a vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; &quot;&lt;/span&gt; ++ b vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;)&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then using the combinators from the other day:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; :+: &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt;) a&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Expr&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;app_id_id&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Term&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;app_id_id&lt;/span&gt; = app (lam id) (lam id)
&lt;span class=&quot;hljs-comment&quot;&gt;-- for suitable definitions of app and lam a la the a la Carte paper.&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = putStrLn . show $ &lt;span class=&quot;hljs-keyword&quot;&gt;safe&lt;/span&gt; app_id_id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Other algebra structures can be derived similarly.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/higher-order-abstract-syntax-a-la-carte/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Rotten Bananas</title><link>https://comonad.com/reader/2008/rotten-bananas/</link><guid isPermaLink="false">https://comonad.com/reader/2008/rotten-bananas/</guid><pubDate>Tue, 25 Mar 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 25 March 2008&lt;/p&gt;&lt;span id=&quot;more-44&quot;&gt;&lt;/span&gt;&lt;p&gt;I have been trying out various representations for higher-order abstract syntax (HOAS) in Haskell, with an eye towards seeing what I can actually use to get real work done and I have run into a few unexpected headaches, and a couple of neat observations. That said, I should probably start by explaining some terminology.&lt;/p&gt;
&lt;p&gt;Encoding a language that binds variables in higher order abstract syntax generally involves constructing an abstract data type that contains functions. A functor for representing expressions from Berendregdt's lambda cube in HOAS goes something like (ignoring any consolidation of binders and sorts)&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a&lt;/span&gt;
    = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; a (a -&amp;gt; a)
    | &lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt; a (a -&amp;gt; a)
    | &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a a
    | &lt;span class=&quot;hljs-type&quot;&gt;Star&lt;/span&gt;
    | &lt;span class=&quot;hljs-type&quot;&gt;Box&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are a number of mathematical functors that are not instances has Haskell's Functor class, such as the above.&lt;/p&gt;
&lt;p&gt;If you don't believe me that F is not a functor, try deriving an instance for fmap for F that satisfies the functor laws:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; id == id
&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; (f . g) == fmap f . fmap g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The reason it can't be is that fmap can really only be defined for 'covariant endofunctors on the category of types'.&lt;/p&gt;
&lt;p&gt;Most covariant functors used in Haskell are among the so-called 'polynomial' functors, meaning that they can be built up out of sums, products and constants.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- covariant in a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ListF&lt;/span&gt; t a = &lt;span class=&quot;hljs-type&quot;&gt;Cons&lt;/span&gt; t a | &lt;span class=&quot;hljs-type&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- covariant in a&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That said, polynomial functors are not the only covariant functors, because you can also have some functions in the type, as long as the type over which you are parameterized only occurs in 'positive' position. The informal way to think about it is that every time you have a parameter on the left of an (-&amp;gt;) in the type, the occurrence switches signs, starting positive, so for some Functors, you can have functions, as long as the parameter occurs only in positive positions. Most of us know some instances of Functor that are covariant, but not polynomial such as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; e a = &lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- covariant in a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; r a = &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; ((&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r) &lt;span class=&quot;hljs-comment&quot;&gt;-- covariant in a&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other hand the following functors are not covariant, because the parameter occurs in negative position somewhere in the type.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ContravariantSample&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Bar&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- contravariant&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;InvariantSample&lt;/span&gt; a = &lt;span class=&quot;hljs-type&quot;&gt;Baz&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-comment&quot;&gt;-- invariant&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could go through and define a 'ContravariantFunctor' type class if you really want:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ContravariantFunctor&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    cofmap :: (b -&amp;gt; a) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But for HOAS you tend to need terms like Lam (a -&amp;gt; a) that have both positive and negative occurrences of a to handle variable binding, so we'll skip to a definition for an invariant functor, which we'll choose to call an exponential functor in contrast to a polynomial, because category theory types like to refer to functions as exponentials, and use the notation b&lt;sup&gt;a&lt;/sup&gt; to denote a function of type (a -&amp;gt; b).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    xmap :: (a -&amp;gt; b) -&amp;gt; (b -&amp;gt; a) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, obviously every Functor is trivially an ExpFunctor, witnessed by the default definition:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;xmapF&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; b) -&amp;gt; (b -&amp;gt; a) -&amp;gt; f a -&amp;gt; f b
&lt;span class=&quot;hljs-title&quot;&gt;xmapF&lt;/span&gt; = const . fmap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And just as people are wont to do with Functor and Monad you could argue that in an ideal world the definition for Functor should change to class ExpFunctor f =&amp;gt; Functor f, but since not that many people use these things, I doubt anyone would be interested in the change.&lt;/p&gt;
&lt;p&gt;This is a sufficiently general definition that you can construct instances for exponential data types such as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; t k) = &lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; (f t) (f . k . g)
    xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt; t k) = &lt;span class=&quot;hljs-type&quot;&gt;Pi&lt;/span&gt; (f t) (f . k . g)
    xmap f g (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) = &lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; (f a) (f b)
    xmap f g &lt;span class=&quot;hljs-type&quot;&gt;Star&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Star&lt;/span&gt;
    xmap f g &lt;span class=&quot;hljs-type&quot;&gt;Box&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Box&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an aside we can define exponential functor composition, just like functor composition if we want to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt; f g e = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;deComp&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; . fmap (fmap f) . deComp
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; `&lt;span class=&quot;hljs-type&quot;&gt;O&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;g&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
  xmap f g = &lt;span class=&quot;hljs-type&quot;&gt;Comp&lt;/span&gt; . xmap (xmap f g) (xmap g f) . deComp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Typically we'd like to represent the recursive part of a functor with another ADT. This makes it easier to go through and apply things like catamorphisms and anamorphisms to them (see &lt;a href=&quot;http://citeseer.ist.psu.edu/meijer91functional.html&quot;&gt;Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire&lt;/a&gt; for more information). Catamorphisms are sometimes called bananas because of the notation from that paper.&lt;/p&gt;
&lt;p&gt;A typical newtype used for explicit &lt;a href=&quot;http://en.wikipedia.org/wiki/Recursive_type&quot;&gt;isorecursion&lt;/a&gt; is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f  = &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;old&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) } &lt;span class=&quot;hljs-comment&quot;&gt;--so its not funny&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if f is a good old fashioned Functor, we can define a pretty straightforward idea of a catamorphism over Nu f. I want to be able to handle ExpFunctor's later, so we'll leave the Functor constraint off of the class and move it to the instance.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f t | t -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    cata :: (f a -&amp;gt; a) -&amp;gt; t -&amp;gt; a
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    cata f = f . fmap (cata f) . old
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And given cata and fmap one can go through and build up a whole host of other recursion schemes, paramorphisms, zygomorphisms, histomorphisms, generalized catamorphisms, ...; the menagerie is quite forbidding and these can be used to tear apart covariant functors with reckless abandon. With the power of a paramorphism you rederive the notion of general recursion, and so you can basically write any recursive function you want. (On the coalgebra side of the house there are anamorphisms, apomorphisms, and all sorts of other beasts for effectively generating covariant functors)&lt;/p&gt;
&lt;p&gt;You can also use them on contravariant functors with some work, because it turns out you can 'square' a contravariant functor to derive a covariant one.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Square&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Square&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;))&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ContravariantFunctor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Square&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fmap f = &lt;span class=&quot;hljs-type&quot;&gt;Square&lt;/span&gt; . cofmap (cofmap f) . unSquare
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is that once you weaken from a Functor all the way to an ExpFunctor, most of that machinery goes out the window.&lt;/p&gt;
&lt;p&gt;Cue the arrival of Erik Meijer and Graham Hutton. They derived a kind of catamorphism for exponential functors back in 1995 in &lt;a href=&quot;http://citeseer.ist.psu.edu/293490.html&quot;&gt;Bananas in Space&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cataMH&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cataMH&lt;/span&gt; f g = f . xmap (cataMH f g) (anaMH f g) . old

&lt;span class=&quot;hljs-title&quot;&gt;anaMH&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; (a -&amp;gt; f a) -&amp;gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;anaMH&lt;/span&gt; f g = &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; . xmap (anaMH f g) (cataMH f g) . g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the similarity and differences between cataMH and the cata described above. In order to satisfy the type of xmap you need not just an operation to fold your structure, but you need an 'unfold' step as well; to run the catamorphism backwards to satisfy the type of xmap, cataMH requires not just an 'algebra structure' (f a -&amp;gt; a) for folding, but it also requires an inverse 'coalgebra structure' (a -&amp;gt; f a) to unfold what it just did.&lt;/p&gt;
&lt;p&gt;In other words, to use the Meijer/Hutton catamorphism to write a pretty printer, you have to write a parser as well; to use it to eval, you must also be able to reify values back into programs.&lt;/p&gt;
&lt;p&gt;Unfortunately we won't be able to get an instance of Cata out of the Meijer/Hutton catamorphism.&lt;/p&gt;
&lt;p&gt;With it in hand, you can write a pretty powerful HOAS representation, but there are some huge caveats to the Meijer-Hutton catamorphism:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Some catamorphisms don't have inverses!&lt;/li&gt;
&lt;li&gt;Since a function in your embedded language is represented as a function in the 'meta-language' Haskell, HOAS functions have the ability to host 'bad terms' that do things that the underlying embedded language can't do like use case to inspect if they were given a lambda or an application as an argument on terms passed to them and do different things accordingly.&lt;/li&gt;
&lt;li&gt;Using the inverse can be very slow&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fortunately, a year later &lt;a href=&quot;http://citeseer.ist.psu.edu/2065.html&quot;&gt;Leonidas Fegaras and Tim Sheard&lt;/a&gt; realized that the main use of the 'unfold step' above was to just undo the damage caused by the fold step and that a full inverse wasn't needed, just a place holder 'place' such that serves as a right-inverse such that:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; f . place = id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem the reduces to the question of how to define place. Fegaras and Sheard were willing (and able) to change every functor to include an extra member name Place and then define as part of each catamorphism that cata f (Place x) = x. They then ensured that Place wasn't abused by the programmer by a complicated type system that we really don't have access to in Haskell. So, if you are able to go into some as-yet-unwritten language where their tagged types exist, then your problems are solved for the most part and you can write general recursion over exponential functors without impossible to find inverses, bad terms or expensive inverse operations.&lt;/p&gt;
&lt;p&gt;A compromise is to realize as much of the Fegaras/Sheard vision as you can reasonably type in Haskell. As noted by Weirich and Washburn, you can move the 'Place' term into the explicit recursion ADT yielding something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)) | &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This obviates the need to modify every single base functor you use to include a Place term -- admittedly at the cost of introducing another case analysis where a bottom can occur because the recursive data type is no longer a newtype.&lt;/p&gt;
&lt;p&gt;We can then readily almost define a catamorphism for this type - ignoring the extra 'a' term in Rec f a for the nonce.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cataFS&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f =&amp;gt; (f a -&amp;gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a -&amp;gt; a
&lt;span class=&quot;hljs-title&quot;&gt;cataFS&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; x) = f (xmap (cataFS f) &lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; x)
&lt;span class=&quot;hljs-title&quot;&gt;cataFS&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Place&lt;/span&gt; x) = x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an aside to build terms to feed to either of these recursive forms, you need to inject values by wrapping them in the recursive constructor:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lamMH&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;lamMH&lt;/span&gt; t k = &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; t k)

&lt;span class=&quot;hljs-title&quot;&gt;lamFS&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a -&amp;gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;lamFS&lt;/span&gt; t k = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; t k)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You'll note a lot of similarity here, and also a superfluous term 'a' floating around in the Fegaras Sheard definition, which is necessary for Place to work its magic.&lt;/p&gt;
&lt;p&gt;Since I want to compare a few different ways to represent HOAS here, lets define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; f t | t -&amp;gt; f &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    roll :: f t -&amp;gt; t
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    roll = &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    roll = &lt;span class=&quot;hljs-type&quot;&gt;Roll&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can use one function for either recursion scheme that we want to use for our particular functor 'F'.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; t =&amp;gt; t -&amp;gt; (t -&amp;gt; t) -&amp;gt; t
&lt;span class=&quot;hljs-title&quot;&gt;lam&lt;/span&gt; t f = roll (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; t f)

&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; t =&amp;gt; t -&amp;gt; t -&amp;gt; t
&lt;span class=&quot;hljs-title&quot;&gt;app&lt;/span&gt; f a = roll (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; f a)

...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem then comes down to the fact that when working with the Fegaras/Sheard form, you have a superfluous term 'a' that can bite you when you go to apply two different catamorphisms to your HOAS term. The first will fix your type to the return type of its catamorphism and you'll be done for when you attempt to apply a different catamorphism that needs a different type.&lt;/p&gt;
&lt;p&gt;One fix, as noted by Washburn and Weirich is to quantify over the a with an explicit forall when working with the Fegaras/Sheard catamorphism. This has the nice side effect that it prevents illegal uses of 'Place'. Moreover, that explicit quantifier allows you to use different catamorphisms over the term.&lt;/p&gt;
&lt;p&gt;So, now instead of being interested in terms of the type 'Rec f a' we want terms of the type 'forall a. Rec f a', but then we run into another problem!&lt;/p&gt;
&lt;p&gt;You can't define a typeclass instance for a type that has a leading explicit 'forall' quantifier, and I for one really like to be able to use typeclasses like Show, Eq, etc over my types.&lt;/p&gt;
&lt;p&gt;However, Shae Erisson and I noticed the fact that you can define the following strange, beautiful but legal newtype to box up the quantifier:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; f = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;runForAll&lt;/span&gt; :: &lt;span class=&quot;hljs-title&quot;&gt;forall&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This lets us define a better catamorphism which doesn't suffer from the monomorphism problems that the previous version did, and finally we get an instance of Cata for the FegarasSheard catamorphism.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    cata f = cataFS f . runForAll
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A lambda calculus pretty printer in the style of Washburn and Weirich's &lt;a href=&quot;http://repository.upenn.edu/cis_reports/43/&quot;&gt;Boxes Go Bananas&lt;/a&gt; goes something like the following (although you need -fallow-undecidable-instances in GHC.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;F&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;t&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    show x = cata phi x vars &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
        phi (&lt;span class=&quot;hljs-type&quot;&gt;Lam&lt;/span&gt; t k) (v:vars) =
            &lt;span class=&quot;hljs-string&quot;&gt;&quot;(\\\\&quot;&lt;/span&gt; ++ v ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;: &quot;&lt;/span&gt; + t vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;. &quot;&lt;/span&gt; ++ k (const v) vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;)&quot;&lt;/span&gt;
        phi (&lt;span class=&quot;hljs-type&quot;&gt;App&lt;/span&gt; a b) vars =
            &lt;span class=&quot;hljs-string&quot;&gt;&quot;(&quot;&lt;/span&gt; ++ a vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot; &quot;&lt;/span&gt; ++ b vars ++ &lt;span class=&quot;hljs-string&quot;&gt;&quot;)&quot;&lt;/span&gt;
        ...
        vars =
            [ [i] | i &amp;lt; - [&lt;span class=&quot;hljs-string&quot;&gt;'a'&lt;/span&gt;..&lt;span class=&quot;hljs-string&quot;&gt;'z'&lt;/span&gt;]] ++
            [i : show j | j &amp;lt;- [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..], i &amp;lt;- [&lt;span class=&quot;hljs-string&quot;&gt;'a'&lt;/span&gt;..&lt;span class=&quot;hljs-string&quot;&gt;'z'&lt;/span&gt;] ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All is not roses, however. We still haven't ruled out bad functions that inspect the functor they are given.&lt;/p&gt;
&lt;p&gt;Washburn and Weirich go off and change the form of the recursion data type yet again to yield an explicit elimination form with some benefits and costs, which I can represent here as:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec'&lt;/span&gt; f a = (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) -&amp;gt; a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As an interesting aside, you may notice some similarities to the type of the continuation monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; r a = &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; ((&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;r&lt;/span&gt;) -&amp;gt; r)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Rec''&lt;/span&gt; w a = &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; a (&lt;span class=&quot;hljs-title&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'll have more to say about this curious use of a monad later on, but unfortunately Rec and Rec'' can't be used with ForAll as they stand, so we have to introduce yet another newtype so that they can be partially applied -- thankfully these are free at runtime!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; f a = &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; { &lt;span class=&quot;hljs-title&quot;&gt;unElim&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) }&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;elim&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; . &lt;span class=&quot;hljs-type&quot;&gt;Cont&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;runElim&lt;/span&gt; = runCont . unElim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can define the relevant typeclasses needed to support all the Fegaras and Sheard machinery for this type:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    roll x = elim $ \f -&amp;gt; f $ xmap (cata f) place x
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Placeable&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    place = elim . const
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f (&lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;f&lt;/span&gt;)) &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    cata f x = runElim (runForAll x) f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After all of that, we basically get the 'iteration library interface' of Boxes Go Bananas packaged up so that we can play with these representations more or less interchangeably.&lt;/p&gt;
&lt;p&gt;Now for the problem.&lt;/p&gt;
&lt;p&gt;Weirich and Washburn's encoding as an elimination form protect the user from bad case analysis by denying you the ability to inspect terms with case at all. This is immediately apparent by the signature of Rec' f a above:&lt;/p&gt;
&lt;p&gt;In their encoding:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cata&lt;/span&gt; x f = f x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, the only thing you can do to a term is apply a catamorphism to it. They even say as much somewhere in the paper.&lt;/p&gt;
&lt;p&gt;No sweat, we can go rederive all of the other stuff thats defined in terms of catamorphism, right? paramorphisms, zygomorphisms, histomorphisms, generalized catamorphisms, and then we can do anything we want, right? Unfortunately, here is where we run out of steam.&lt;/p&gt;
&lt;p&gt;A catamorphism isn't strong enough to encode general recursion without fmap. In order to rederive general recursion from a catamorphism you need at least a paramorphism. Normally we can define a paramorphism in terms of our catamorphism with the use of fmap, but as we are working over merely an exponential functor we do not have fmap!&lt;/p&gt;
&lt;p&gt;I ran headlong into this wall, while trying to derive a minimalist dependently-typed lambda calculus implementation using the Boxes Go Bananas encoding, because typechecking requires normal form reduction, which could be cleanly encoded as a paramorphism, but which couldn't seem to be represented in the Boxes Go Bananas style.&lt;/p&gt;
&lt;p&gt;Depending on how bad we want to be, we can get out of the Washburn/Weirich or Fegaras/Sheard sandboxes and into one of the others. Though curiously we can't get back out of the Meijer/Hutton-style unless we have a full Functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;reroll&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f t, &lt;span class=&quot;hljs-type&quot;&gt;Rollable&lt;/span&gt; f t') =&amp;gt; t -&amp;gt; t'
&lt;span class=&quot;hljs-title&quot;&gt;reroll&lt;/span&gt; = cata roll

&lt;span class=&quot;hljs-comment&quot;&gt;-- | safe $$ hoas-expression&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;safe&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. &lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; f)
&lt;span class=&quot;hljs-title&quot;&gt;safe&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | unsafe $$ hoas-expression&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;unsafe&lt;/span&gt; :: (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; a. &lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f a) -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f)
&lt;span class=&quot;hljs-title&quot;&gt;unsafe&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | cast to Meijer/Hutton&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;toMH&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f t, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f) =&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt; f
&lt;span class=&quot;hljs-title&quot;&gt;toMH&lt;/span&gt; = cata &lt;span class=&quot;hljs-type&quot;&gt;Nu&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;-- | cast to Washburn/Weirich&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;toWW&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f t, &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f) =&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Elim&lt;/span&gt; f)
&lt;span class=&quot;hljs-title&quot;&gt;toWW&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (reroll x)

&lt;span class=&quot;hljs-comment&quot;&gt;-- | cast to Fegaras/Sheard&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;toFS&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Cata&lt;/span&gt; f t, &lt;span class=&quot;hljs-type&quot;&gt;ExpFunctor&lt;/span&gt; f) =&amp;gt; t -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Rec&lt;/span&gt; f)
&lt;span class=&quot;hljs-title&quot;&gt;toFS&lt;/span&gt; x = &lt;span class=&quot;hljs-type&quot;&gt;ForAll&lt;/span&gt; (reroll x)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems we can get to a point where the System &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;F_\omega&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;ω&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; fragment of Haskell protects us from ourselves, preventing bad case analysis and abuse of the place term, but in the process we give up general recursion.&lt;/p&gt;
&lt;p&gt;For now, I think I have to hop out to at least the Fegaras and Sheard encoding to get any work done.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/haskell/hoas/Exponential.hs&quot;&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/rotten-bananas/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Elgot Algebras</title><link>https://comonad.com/reader/2008/elgot-algebras/</link><guid isPermaLink="false">https://comonad.com/reader/2008/elgot-algebras/</guid><pubDate>Tue, 01 Jan 2008 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 1 January 2008&lt;/p&gt;&lt;p&gt;Wordpress changed the slug of this post, but Planet Haskell has the old link.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/elgot-coalgebras/&quot;&gt;Here is the actual content&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2008/elgot-algebras/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Parameterized Monads in Haskell</title><link>https://comonad.com/reader/2007/parameterized-monads-in-haskell/</link><guid isPermaLink="false">https://comonad.com/reader/2007/parameterized-monads-in-haskell/</guid><pubDate>Fri, 13 Jul 2007 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 13 July 2007&lt;/p&gt;&lt;span id=&quot;more-41&quot;&gt;&lt;/span&gt;&lt;p&gt;Recently &lt;a href=&quot;http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros&quot;&gt;Eric Kidd&lt;/a&gt; and &lt;a href=&quot;http://sigfpe.blogspot.com/2007/06/how-to-write-tolerably-efficient.html&quot;&gt;Dan Piponi&lt;/a&gt; have used a bit of &lt;a href=&quot;http://okmij.org/ftp/Haskell/types.html#restricted-datatypes&quot;&gt;type hackery by Oleg Kiselyov&lt;/a&gt; and -fno-implicit-prelude to build some interesting restricted monads, like the Wadler Set and Bag monads.&lt;/p&gt;
&lt;p&gt;There is another interesting monad variation - a parameterized monad - where the monad carries around an additional parameter at the type level such as a type-level set of effects. One really good example of this is the separation logic monad in &lt;a href=&quot;http://www.eecs.harvard.edu/~aleks/papers/hoarelogic/jfpsep07.pdf&quot;&gt;Hoare Type Theory&lt;/a&gt;. The pre- and post- conditions can be viewed as the parameter carried around on that monad. &lt;a href=&quot;http://citeseer.ist.psu.edu/254302.html&quot;&gt;Wadler and Thiemann&lt;/a&gt;, &lt;a href=&quot;http://citeseer.ist.psu.edu/273929.html&quot;&gt;Jean-Christophe Filliâtre&lt;/a&gt; and others have explore this notion for encoding effects.&lt;/p&gt;
&lt;p&gt;This prompts the question of if parameterized monads can be implemented directly in Haskell. Indeed they can, but a simple version fails with the signature:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;BadHaskell&lt;/span&gt; m p p' p'' | p p' -&amp;gt; p'' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    return :: a -&amp;gt; m p a
    fail :: a -&amp;gt; m p a
    (&amp;gt;&amp;gt;=) :: m p a -&amp;gt; (a -&amp;gt; m p' a) -&amp;gt; m p'' a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This of course runs afoul of the fact that all of the parameters are not mentioned in return, so we have to break it apart into two or three classes.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; m p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    return :: a -&amp;gt; m p a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; m p &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fail :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; m p a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; m p p' p'' | p p' -&amp;gt; p'' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    (&amp;gt;&amp;gt;=) :: m p a -&amp;gt; (a -&amp;gt; m p' a) -&amp;gt; m p'' a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By splitting off fail, we can make it so that it is illegal to use an incomplete pattern on certain monads, a small win, but it may be useful in a later post.&lt;/p&gt;
&lt;p&gt;However, there turns out to be quite some awkwardness from the perspective of type inference with this type. In particular we are used to the types of our monads being able to be inferred from the type of their results, but we lose this inference on return. Moreover, we can't just use existing monads under this syntax, we'd have to lift them into a newtype that accepted the additional parameter.&lt;/p&gt;
&lt;p&gt;Ignoring the problems with existing monads, and correcting the type inference problem directly by adding fundeps doesn't help as&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; m p p' p''
  | p -&amp;gt; p' p''
  , p' -&amp;gt; p p''
  , p'' -&amp;gt; p p'
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    (&amp;gt;&amp;gt;=) :: m p a -&amp;gt; (a -&amp;gt; m p' a) -&amp;gt; m p'' a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is too restrictive and could be shown that under a strict interpretation of the laws, would never be able to be made to satisfy the monad laws except in the base case, because of the inability to construct an associative operation combining the parameters that isn't trivial.&lt;/p&gt;
&lt;p&gt;As an aside, speaking of failing monad laws, it is interesting to note that the Set restricted monad actually fails a monad law given that functions in haskell need not respect equality, since &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo&gt;&amp;gt;&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x = y =&amp;gt; f x = f y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.7335em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; fails to hold in general for user defined equality as used by the Set monad, as noted by Andrea Vezzosi on #haskell, the order of association can make a difference as to the result of the computation. This is arguably a minor quibble as you wouldn't be using it unless you knew the type you were going to pass around and how your functions worked on it with respect to its notion of equality.&lt;/p&gt;
&lt;p&gt;Turning back to the issue of being unable to pass traditional monads into this type, we realize that having a separate m and p parameters to the type class is redundant as you can generate an equivalent notion by letting m vary.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    return :: a -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Fail&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    fail :: &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; m m' m'' | m m' -&amp;gt; m'' &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    (&amp;gt;&amp;gt;=) :: m a -&amp;gt; (a -&amp;gt; m' a) -&amp;gt; m'' a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This still has the problem that the type of return is not inferable, but now at least we can derive instances of these classes for instances of Monad. Of course, if we create a generic instance for&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Control.Monad &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Old
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Old&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; m m m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt; (&amp;gt;&amp;gt;=) = (&lt;span class=&quot;hljs-type&quot;&gt;Old&lt;/span&gt;.&amp;gt;&amp;gt;=)
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we then run afoul of the fact that we can't define any other interesting instances because the compiler won't know which way to go with type class inference.&lt;/p&gt;
&lt;p&gt;However, even without that we can import each monad in turn, and define some interesting interfaces between them:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt; [] [] &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; a &amp;gt;&amp;gt;= f = f a
    &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; &amp;gt;&amp;gt;= _ = []
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- testMaybeList :: [Int] = [2,4]&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;testMaybeList&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &amp;gt;&amp;gt;= \x -&amp;gt; [x*&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,x*&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Admittedly there is an &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n^2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; combinatorial explosion of combinations and not all of them have clear semantics, but we can choose to implement only the ones that have an unambiguous interpretation and leave off the rest and pay as we go, implementing them as needed. A more mature version of this might provide an interesting alternative/supplement to the MTL approach and can be viewed as a limited fragment of &lt;a href=&quot;http://citeseer.ist.psu.edu/619712.html&quot;&gt;Lüth and Ghani's monad composition through coproducts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, we still haven't solved the return problem, but it turns out that monad laws can come to the rescue.&lt;/p&gt;
&lt;p&gt;If we start to implement a number of these we notice a pattern when it comes to the Identity monad. In general we can define instances of Bind for the Identity monad for any monad presuming we can liftM, to handle the case on the right, but since liftM requires a sort of circular dependency loop, we choose to make Bind enforce the availability of fmap, allow overlapping instances, and then define:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m'&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;m''&lt;/span&gt;) =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; m m' m''
 | m m' -&amp;gt; m''
  &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    (&amp;gt;&amp;gt;=) :: m a -&amp;gt; (a -&amp;gt; m' b) -&amp;gt; (m'' b)
    (&amp;gt;&amp;gt;)  :: m a -&amp;gt; m' b -&amp;gt; m'' b
    m &amp;gt;&amp;gt; k = m &amp;gt;&amp;gt;= const k
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    m &amp;gt;&amp;gt;= f = f (runIdentity m)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; a &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    m &amp;gt;&amp;gt;= f = fmap (runIdentity . f) m
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;-- and to disambiguate between the above instances...&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Bind&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    m &amp;gt;&amp;gt;= f = f (runIdentity m)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The correctness of this is in fact enforced by the monad laws as these instances can be read as the familiar laws once you remove the noise of the Identity monad:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;return&lt;/span&gt; m &amp;gt;&amp;gt;= f = f m
&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt; &amp;gt;&amp;gt;= return . f = fmap f m
&lt;span class=&quot;hljs-title&quot;&gt;return&lt;/span&gt; m &amp;gt;&amp;gt;= f = f m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us a single natural notion of return for all monads that we can use and still glue together via &amp;gt;&amp;gt;=:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    returnM :: a -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;return&lt;/span&gt; :: a -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a
&lt;span class=&quot;hljs-title&quot;&gt;return&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;Old&lt;/span&gt;.return
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the problem is if you write a statement like &lt;code&gt;return 2 &amp;gt;&amp;gt;= \x -&amp;gt; return (x+1)&lt;/code&gt;, you can have the Identity type percolate out of your monad expression, even when you were expecting a ListT or State monad or something more interesting, so we need a way to transform values from the Identity monad to an arbitrary monad for use when you want its type to conform to an external signature.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Go&lt;/span&gt; n m &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
        go :: n a -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Return&lt;/span&gt; a =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Go&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Identity&lt;/span&gt; a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    go = returnM . runIdentity
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Go&lt;/span&gt; a a &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    go = id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, now we can tell our code to &lt;code&gt;go (do something)&lt;/code&gt; and it will transform any lingering Identities to whatever monadic type is inferred for the go statement in its current context.&lt;/p&gt;
&lt;p&gt;This has the advantage that pure fragments in our monadic sugar can avoid carrying around the rest of the monadic plumbing, even though they use the same bind operator to string it all together.&lt;/p&gt;
&lt;p&gt;We can perform similar surgery on the MonadPlus class, tearing it apart into two pieces, breaking out a canonical mzero implementation as a trivial monad that just projects everything to bottom, and having Go erase any lingering mzeros that percolate out of our expression. Rather than reproduce it here, I point to a darcs repository that I just created. You can use darcs to get &lt;a href=&quot;http://comonad/com/haskell/monad-param&quot;&gt;http://comonad/com/haskell/monad-param&lt;/a&gt; or pull the package from hackage. The interesting bits are in Control.Monad.Parameterized and &lt;a href=&quot;https://comonad.com/haskell/monad-param/dist/doc/html/Control-Monad-Parameterized.html&quot;&gt;HTML documentation is available&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This package re-exports the MTL and STM monads to avoid the requirement that the end user explicitly import Control.Monad.* masking off the members of Control.Monad each time and it provides some interesting mixins.&lt;/p&gt;
&lt;p&gt;Caveat: It appears that GHC enforces the fact that the arguments and results of (&amp;gt;&amp;gt;=) must have a signature like&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(&amp;gt;&amp;gt;=) :: forall m a. (...) =&amp;gt; m a -&amp;gt; (a -&amp;gt; m b) -&amp;gt; m b&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;insofar as when you use the do-sugar, your types will not be able to vary. Ideally it should be able to get by with a more liberal signature, but it seems like no one has needed it before now.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2007/parameterized-monads-in-haskell/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Updated Data.Type.*</title><link>https://comonad.com/reader/2007/updated-datatype/</link><guid isPermaLink="false">https://comonad.com/reader/2007/updated-datatype/</guid><pubDate>Fri, 13 Jul 2007 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 13 July 2007&lt;/p&gt;&lt;p&gt;Updated my little &lt;a href=&quot;https://comonad.com/haskell/type-int/&quot;&gt;type-level 2s and 16s complement integer library&lt;/a&gt; to be ghc 6.6 friendly and uploaded it to &lt;a href=&quot;https://hackage.haskell.org/package/type-int-0.4&quot;&gt;hackage&lt;/a&gt; based on popular (er.. ok, well, singular) demand.&lt;/p&gt;
&lt;p&gt;O.K. it was more of a polite request, but I did update it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2007/updated-datatype/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Javascript Interpreter, Recompiler, Atomizer, Threading Library…</title><link>https://comonad.com/reader/2007/javascript-interpreter-recompiler-atomizer-threading-library/</link><guid isPermaLink="false">https://comonad.com/reader/2007/javascript-interpreter-recompiler-atomizer-threading-library/</guid><pubDate>Mon, 21 May 2007 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 21 May 2007&lt;/p&gt;&lt;p&gt;It recently came to my attention that most of the actual code for my old javascript libraries was not accessible from the Wiki. Apparently, I deleted the wrong directory in a spate of cleaning several months back and the links just quietly went dead.&lt;/p&gt;
&lt;p&gt;The URL &lt;a href=&quot;https://comonad.com/assets/imported/398688ed5e9f-jslib.tar.gz&quot;&gt;http://comonad.com/jslib.tar.gz&lt;/a&gt; contains an archive that is a little out of date, but should contain most of the framework. (In particular the Recompiler seems to be missing pieces) I haven't had a chance to check it for sanity, completeness or consistency.&lt;/p&gt;
&lt;p&gt;It relies on the use of the C preprocessor on the back-end. I may have forgotten some scripts it needs to actually build. I just used a linux box with spidermonkey and rhino to test. If there is any interest I'll try to drum up the rest of the pieces and make things functional, but I haven't heard much chatter about these since I moved things over from slipwave.com.&lt;/p&gt;
&lt;p&gt;You hereby have the right to use this under the Apache Public License 2.0 with my name substituted in for the Apache Foundation, since thats what I said I would release it under. If you need a more permissive license feel free to ask.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2007/javascript-interpreter-recompiler-atomizer-threading-library/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>##logic</title><link>https://comonad.com/reader/2006/logic/</link><guid isPermaLink="false">https://comonad.com/reader/2006/logic/</guid><pubDate>Thu, 09 Nov 2006 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 9 November 2006&lt;/p&gt;&lt;p&gt;A number of us from the freenode &lt;a href=&quot;irc://irc.freenode.net/%23haskell&quot;&gt;#haskell&lt;/a&gt; channel have gone and formed/revived &lt;a href=&quot;irc://irc.freenode.net/%23%23logic&quot;&gt;##logic&lt;/a&gt; to avoid overwhelming the main Haskell channel with traffic. Originally, I just wanted to revive the #logic channel that was already there, but upon talking to the freenode staff, it appears that they have &lt;a href=&quot;http://freenode.net/policy.shtml#topicalchannels&quot;&gt;channel naming guidelines&lt;/a&gt; that preclude topical discussion channels getting single # names without some sort of clear trademark. They were however nice enough to forward the previous #logic channel to the new location.&lt;/p&gt;
&lt;p&gt;In any event, if you are interested in logic at pretty much any level, feel free to stop by the channel.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2006/logic/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Generalizing (.)</title><link>https://comonad.com/reader/2006/generalizing-dot/</link><guid isPermaLink="false">https://comonad.com/reader/2006/generalizing-dot/</guid><pubDate>Thu, 09 Nov 2006 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 9 November 2006&lt;/p&gt;&lt;span id=&quot;more-35&quot;&gt;&lt;/span&gt;&lt;p&gt;If we take a look at the Haskell (.) operator:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;(.) :: (a -&amp;gt; b) -&amp;gt; (e -&amp;gt; a) -&amp;gt; e -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and take a moment to reflect on the type of fmap&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; b) -&amp;gt; f a -&amp;gt; f b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the unnamed Reader monad from &lt;a href=&quot;http://haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-Reader.html&quot;&gt;Control.Monad.Reader&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; ((-&amp;gt;) r)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we see that fmap applied to the Reader functor rederives (.).&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;fmap_reader&lt;/span&gt; :: (a -&amp;gt; b) -&amp;gt; (e -&amp;gt; a) -&amp;gt; e -&amp;gt; b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So if we were willing to forgo ease of learning, and to bake in the Reader monad as a primitive, we could quite concisely redefine (.) to give it a more general signature:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;module&lt;/span&gt; Dot &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Control.Monad.Reader
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Prelude &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; ((.))
&lt;span class=&quot;hljs-keyword&quot;&gt;infixr&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; .
(.) :: &lt;span class=&quot;hljs-type&quot;&gt;Functor&lt;/span&gt; f =&amp;gt; (a -&amp;gt; b) -&amp;gt; f a -&amp;gt; f b
(.) = fmap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this context, existing code continues to type check. For instance,&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;((+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) . (*&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)) &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; ==&amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;17&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the . above doubles as filling the role of the * map operator mentioned in Richard Bird's 1990 Calculus of Functions paper generalized to any Functor.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;((+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) . (*&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)) . [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;] ==&amp;gt; [&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;,&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;,..&lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;]
((+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) . (*&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)) . &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; ==&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;17&lt;/span&gt;
((+&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) . (*&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)) . &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt; ==&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was able to test this with the just about every example golfed back and forth on the &lt;a href=&quot;irc://irc.freenode.net/%23haskell&quot;&gt;#haskell&lt;/a&gt; channel in the last 6 months.&lt;/p&gt;
&lt;p&gt;I'm not advocating this as a practice for Haskell as it is somewhat terrifying to think of how to teach to new programmers, but I found the exercise to be enlightening.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2006/generalizing-dot/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Overloaded Functions with Subtyping</title><link>https://comonad.com/reader/2006/overloaded-functions-with-subtyping/</link><guid isPermaLink="false">https://comonad.com/reader/2006/overloaded-functions-with-subtyping/</guid><pubDate>Wed, 01 Nov 2006 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 1 November 2006&lt;/p&gt;&lt;p&gt;Was reading Castagna, Ghelli, and Longo's 1995 paper on &quot;&lt;a href=&quot;http://citeseer.ist.psu.edu/125897.html&quot;&gt;A Calculus for Overloaded Functions with Subtyping&lt;/a&gt;&quot; today and in it they have to jump through some hoops to index their '&amp;amp;' types to keep them well behaved under β-reduction.&lt;/p&gt;
&lt;p&gt;It seems to me, at least from my back-of-the-envelope scribblings, that if you &lt;a href=&quot;https://comonad.com/reader/wiki/&quot;&gt;CPS transform&lt;/a&gt; the calculus before, that the main technical innovation (overloaded functions using the tighter run-time type information) remains intact, but the need for this technical trick goes away. In this case you know what the reduction will evaluate out to regardless of call-by-value or call-by-need (just bottom), and if the specification changes during evaluation it is still sound, so no need for an index.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;¬&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;¬&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0.22em&quot; rspace=&quot;0.22em&quot;&gt;&amp;amp;&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;¬&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;mtext&gt;-I&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M:W_1 \leq \lbrace\neg U_i\rbrace_{i\leq(n-1)} \qquad  \Gamma \vdash N : W_2 \leq \neg U_n}{\Gamma \vdash (M \mathbin{\&amp;amp;} N) : \lbrace \neg U_i \rbrace_{i \leq n }}\;\lbrace\rbrace\text{-I}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.6136em;vertical-align:-0.52em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.0936em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;¬&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;&lt;span class=&quot;mclose mtight&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:0em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2401em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.5686em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3173em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.1389em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;¬&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;&lt;span class=&quot;mclose mtight&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.3448em;margin-left:0em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5357em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3695em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:2.8571em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3173em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.1389em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;¬&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1645em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.52em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;¬&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mrow&gt;&lt;mi&gt;min&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;∙&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mo&gt;⊥&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;{&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;}&lt;/mo&gt;&lt;mtext&gt;-E&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : \lbrace \neg U_i \rbrace_{i \in I} \qquad  \Gamma \vdash N : U \qquad  U_j = \min_{i \in I} \lbrace U_i \vert U \leq U_i \rbrace }{\Gamma \vdash M \bullet N : \perp }\;\lbrace\rbrace\text{-E}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.3773em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:1.0323em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∙&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:⊥&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.5073em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;¬&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;&lt;span class=&quot;mclose mtight&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.3567em;margin-left:0em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;∈&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1712em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:2.8571em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:2.8571em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0572em;&quot;&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2819em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mop mtight&quot;&gt;&lt;span class=&quot;mop mtight&quot;&gt;&lt;span class=&quot;mtight&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.3567em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;∈&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1712em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen mtight&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3281em;&quot;&gt;&lt;span style=&quot;top:-2.357em;margin-left:-0.109em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.143em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose mtight&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;-E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The above then would requires explicit continuations and might interfere with rederiving tupling from the overloading mechanism alone, but seems to eliminate some of the barriers they mention to the higher order case. However, I'm not convinced it is a net win regardless, because it would require a notion of typecase.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2006/overloaded-functions-with-subtyping/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>WikiPress</title><link>https://comonad.com/reader/2006/wikipress/</link><guid isPermaLink="false">https://comonad.com/reader/2006/wikipress/</guid><pubDate>Thu, 26 Oct 2006 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 October 2006&lt;/p&gt;&lt;p&gt;I almost have the blog integrated with the old &lt;a href=&quot;https://comonad.com/reader/wiki/&quot;&gt;slipwave&lt;/a&gt; wiki content. I kludged something together to display it in WordPress. While I may add a flashy dynamic in-page loading feature like &lt;a href=&quot;http://www.tiddlywiki.com/&quot;&gt;TiddlyWiki&lt;/a&gt;, for right now its functional and backwards compatible with my old content and gracefully degrades in the absence of javascript.&lt;/p&gt;
&lt;p&gt;By way of example, you might try to &lt;a href=&quot;https://comonad.com/reader/wiki/&quot;&gt;view some Haskell source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This also might provide better context when I start to talk about things like &lt;a href=&quot;https://comonad.com/reader/wiki/&quot;&gt;continuations&lt;/a&gt; because I can link right inline to more extended static content.&lt;/p&gt;
&lt;p&gt;This also provides me with a more convenient venue for static content than WordPress' default page management system.&lt;/p&gt;
&lt;p&gt;Please, let me know if some bit of markup doesn't show up right.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2006/wikipress/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Hello, World!</title><link>https://comonad.com/reader/2006/hello-world/</link><guid isPermaLink="false">https://comonad.com/reader/2006/hello-world/</guid><pubDate>Tue, 17 Oct 2006 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 17 October 2006&lt;/p&gt;&lt;pre tabindex=&quot;0&quot; aria-label=&quot;Haskell code&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Control.Comonad &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; Comonad
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;qualified&lt;/span&gt; Edward &lt;span class=&quot;hljs-keyword&quot;&gt;hiding&lt;/span&gt; (&lt;span class=&quot;hljs-title&quot;&gt;personal_details&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; Blog.Software

&lt;span class=&quot;hljs-comment&quot;&gt;-- Hello, World!&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Blog&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Comonad&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
    url = &lt;span class=&quot;hljs-string&quot;&gt;&quot;http://comonad.com/reader&quot;&lt;/span&gt;
    author = &lt;span class=&quot;hljs-type&quot;&gt;Edward&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Kmett&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt; = forever $ post stuff
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Syntax highlighting works.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;var&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{}{\Gamma, x:\tau \vdash x:\tau}\;\text{var}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.9117em;vertical-align:-0.4811em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.394em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4811em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;var&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;σ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;λ&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;σ&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;σ&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;abs&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma,x:\sigma \vdash M:\tau}{\Gamma \vdash \lambda x : \sigma. M : \sigma \rightarrow \tau}\;\text{abs}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2772em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9322em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;λ&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.4461em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mpunct mtight&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;abs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;σ&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;σ&lt;/mi&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Γ&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;τ&lt;/mi&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mtext&gt;app&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt; \frac{\Gamma \vdash M : \sigma \rightarrow \tau \qquad  \Gamma \vdash N:\sigma}{\Gamma \vdash M N : \tau}\;\text{app}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:1.2251em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8801em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;katex-sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1132em;&quot;&gt;τ&lt;/span&gt;&lt;span class=&quot;mspace mtight&quot; style=&quot;margin-right:2.8571em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;Γ&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;σ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord&quot;&gt;app&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Apparently, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;LaTeX&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\LaTeX&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;katex-base&quot;&gt;&lt;span class=&quot;katex-strut&quot; style=&quot;height:0.8988em;vertical-align:-0.2155em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord textrm&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.36em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;span style=&quot;top:-2.905em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord textrm mtight katex-sizing reset-size6 size3&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord text&quot;&gt;&lt;span class=&quot;mord textrm&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.4678em;&quot;&gt;&lt;span style=&quot;top:-2.7845em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord textrm&quot;&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2155em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:-0.125em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord textrm&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; works.&lt;/p&gt;
&lt;figure class=&quot;category-diagram&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/lifting-square.svg&quot; alt=&quot;Commutative square: e from A to B is epic; m from C to D is monic; f maps A to C and g maps B to D. A dashed lift h maps B to C.&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Commutative diagrams, check.&lt;/p&gt;
&lt;p&gt;All systems go.&lt;/p&gt;
&lt;p&gt;World, meet blog; blog, meet world.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2006/hello-world/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Harmless Algorithms — Part 4: A Hybrid Approach to Visibility</title><link>https://comonad.com/reader/2001/harmless-algorithms-4/</link><guid isPermaLink="false">https://comonad.com/reader/2001/harmless-algorithms-4/</guid><pubDate>Mon, 19 Feb 2001 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 19 February 2001&lt;/p&gt;&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This column will discuss an example of a hybrid visibility algorithm from a few-year-old test engine of mine, which used approaches from the previous columns. Providing the terminology to give the explanation below was the main thrust of the original Harmless Algorithms columns, but I quite simply never found the time to finish. My career has taken me far away from 3d graphics. Well, since a number of people have been nagging me about it and it has been over a year since my last update, here goes.&lt;/p&gt;
&lt;p&gt;Hybrid Visibility:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#goals&quot;&gt;Goals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#octree&quot;&gt;Octree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#bspcache&quot;&gt;BSP Cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#lights&quot;&gt;Point Lights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#rendering&quot;&gt;Rendering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/#summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;goals&quot;&gt;&lt;/span&gt;First of all, lets state our goals for this particular engine. I want to manage a million polygon scene with some highly dynamic areas and some very stable portions. I also want to minimize level compilation time to facilitate rapid prototyping by the art staff. I need fast collision detection so I can afford to run physics. The engine is geared for a primarily indoor scene, so I can avoid dealing with horizon issues, or failing that always fall back on a far clip plane. I also want to experiment with shadow casting point lights, because of the ambience I want to give the world.&lt;/p&gt;
&lt;p&gt;With these goals in mind, I'll really just dive into the choices made to support this engine, rather than the reasoning behind the different choices made. Some of them will seem rather counter-intuitive, and they very well may be wrong for the type of engine the typical reader of this column may wish to build. Some of the choices were made simply because of some feature that I wanted to support that I could not support through a conventional approach (i.e. shadow casting point lights) and may induce a global suboptimization in search of a single goal. All of game engine design is about trade-offs, and I do not mean to try to prove that the approach below is the perfect approach, merely that it is an approach.&lt;/p&gt;
&lt;h2 id=&quot;octree&quot;&gt;Octree&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;octree&quot;&gt;&lt;/span&gt;The first piece is to use an &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; to divide space up into manageable pieces. The scene preprocessor just grabs polygons and dumps them into &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; buckets, recursing until a maximum depth is reached or a reasonable number of polygons per&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; node (around 50) is reached.&lt;/p&gt;
&lt;p&gt;Now, I could stop here, clip the polygons to the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; and traverse my scene using a neighbor traversal of the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; structure, by inserting checking each of the polygons in the node against a &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#cbuffer&quot;&gt;C-Buffer&lt;/a&gt; and rendering the ones that pass, then inserting all of the nodes into the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#cbuffer&quot;&gt;C-Buffer&lt;/a&gt; before checking the faces of the tree against the c-buffer and traversing outwards. The problem is this does not provide me with intra-node polygon culling (No polygon within the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; node can occlude any other polygon within the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; node), and I have no way to achieve front-to-back sorting within the node, and my collision detection times are terrible. This would be fine, if I didn't want to deal with collision or shadow casting point lights.&lt;/p&gt;
&lt;h2 id=&quot;bsp-cache&quot;&gt;BSP Cache&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;bspcache&quot;&gt;&lt;/span&gt;So, instead I decide to go with miniature &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt;s inside of the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; nodes, and to really play devil's advocate, I don't even precompile them. Before you panic, please consider that these individual &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt;s have very manageable polygon counts (usually 50 or less), and so the nonlinearities of the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; compilation process are minimized. 70,000&lt;sup&gt;3&lt;/sup&gt; polygons for a 70,000 polygon scene in a Quake-style engine vs 50&lt;sup&gt;3&lt;/sup&gt; performed 1400 times (2000 allowing for shared polygons) differs by several orders of magnitude. ~350 trillion operations vs. 250 million operations is quite a spread, especially when you consider that the 250 million operation version can be handled in chunks of 125,000 operations. Please note that these numbers are worst case scenarios. Also note that this is for only a 70,000 polygon scene. As the scene approaches a million polygons, these numbers become far more ridiculous. (1e18 vs 2.5e9)&lt;/p&gt;
&lt;p&gt;The polygon soup is tagged with what &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; nodes they belong to and are accessible through lists from the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; nodes themselves, so when I need to compile a node into the mini-&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; cache, I just pass in each of the polygons known to be in the node to the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; compiler. The &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; compiler does not bother balancing the tree because the computational overhead of balancing is worse than the pathological cases an unbalanced tree can induce. The compiler generates clipped polygon fragments which are used for visibility determination, but keeps pointers from the fragments to the original polygons. The mini&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; cache is maintained on a LRU (least recently used) basis. You could gain a global speed-up by removing the cache and precompiling the&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt;s, but you would lose the ability to perform gross geometry changes by changing the polygons or large-scale objects that occupy a set of nodes and expiring their LRU cache entries.&lt;/p&gt;
&lt;p&gt;When performing a front-to-back traversal of the node, you walk the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; inserting fragments into your visibility system (Either &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#cbuffer&quot;&gt;C-Buffer&lt;/a&gt; or &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#beamtrees&quot;&gt;Beam Tree&lt;/a&gt; have their own relative merits, depending on display resolution and if you are using anti-aliasing), but if you insert a fragment you render the whole polygon (skipping it of course if you have already inserted another fragment from this same polygon). Rendering the scene could still be done ignoring the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt;, using the approach above if you wish - and may be considerably faster if the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; fragments too heavily, but the presence of a front-to-back structure is useful for collision detection and complex lighting. If the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; is too fragmented then the cache hit of walking the polygons in the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; node twice to render then insert into the fine occlusion culling algorithm is less than the overhead of walking the structure.&lt;/p&gt;
&lt;p&gt;The real purpose of the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; is to provide something to lean on for collision detection. &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; collision detection algorithms are among the fastest in the industry and are very elegant and pleasant to code.&lt;/p&gt;
&lt;p&gt;Other uses for the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; are real-time CSG, which is useful if you really want to blow holes in walls. CSG of a convex solid against a &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; is actually a surprisingly straight forward process. The problem is the number of polygons will increase dramatically over time if you leave this unchecked, and so it really needs good in-game support and reasoning to be practical.&lt;/p&gt;
&lt;p&gt;I should stress that characters are not part of the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt;. Their moving polygon count renders them far too complex to reasonably insert into such a structure.&lt;/p&gt;
&lt;h2 id=&quot;point-lights&quot;&gt;Point Lights&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;lights&quot;&gt;&lt;/span&gt;Now we have reasonable collision detection, and a solid scene traversal which will prevent us from seeing things which aren't there, with safety valves for their more pathological cases. Let there be light.&lt;/p&gt;
&lt;p&gt;Note that thus far there hasn't been much of a preprocessing step. Dumping polygons into &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; buckets can be done, worst case, as the engine loads. This is a good thing for rapid prototyping. However, we all know that you can't get away with radiosity under such conditions. So, if you want radiosity, you'll have to preprocess it. On the other hand, this will doom any attempt at dynamic geometry in the areas in which you pre-light, because it will not properly adapt to environmental changes.&lt;/p&gt;
&lt;p&gt;My answer was to go goth and move to harsher lighting. The Beam Tree algorithm from the earlier columns can be used not only for visibility but to determine the visible polygon fragments in a scene from a given point. These fragments happen to directly correspond to the fragments that would be lit from a light source at that point.&lt;/p&gt;
&lt;p&gt;What is required is a front-to-back traversable scene structure and a &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#beamtrees&quot;&gt;Beam Tree&lt;/a&gt; per light. If you provide linear fall off for the light source you can terminate within a known distance of the source light, providing caps on the time the lighting algorithm will consume. Also, you can 'render' lights on a cached basis, because the polygon fragments lit by a given point light do not change from frame to frame unless the geometry is moving. If you limit their use to areas of low dynamic geometry and/or limited CSG, then you'll do fine.&lt;/p&gt;
&lt;h2 id=&quot;rendering&quot;&gt;Rendering&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;rendering&quot;&gt;&lt;/span&gt;First of all, I'm going to need to stand more of the conventional rendering process on its ear. Instead of rendering textures first, I'll render light. This way I can use additive textures to add multiple lights to the same surface. The cost of this is that this engine cannot use detail textures. If you want ambient light you can render it by rendering an ambient light polygon as a base. Otherwise, rendering a black starting polygon will do. Then render the polygon fragments for each light source affecting this surface. (Cached as a list in the polygon). Any bumpmapping type pass can also be performed here. Finally render the actual texture for the polygon using a multiplicative pass.&lt;/p&gt;
&lt;p&gt;If you want to move back towards a conventional rendering pipeline you could in theory render the point lights to a lightmap and apply the lightmap as a multiplicative post-process. However this will mean considerably more texture memory usage and thrashing of the texture memory will now be guaranteed as will the overhead of performing software lighting on the texture. Using the approach above, texture memory remains stable and available for use by more textures.&lt;/p&gt;
&lt;p&gt;With some tweaking you can use the lighting algorithm to project light through stained glass and you can provide some cheap volumetric lighting effects by using the edges in the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#beamtrees&quot;&gt;Beam Tree&lt;/a&gt; to provide you edges for volumetric light streamers. They are not physically accurate, but they can look pretty good anyways. You can mix and match with the standard bag of tricks, like putting billboard coronas around the light when looking right at it and/or a lens flare if you want to be tacky, etc.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;summary&quot;&gt;&lt;/span&gt;My primary goal for this column was to show the ways that a number of innocuous algorithms that in-and-of-themselves are not very useful can be strung together to achieve goals that none of them can achieve alone. For example, a &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP&lt;/a&gt; could not handle the dynamic geometry or even the sheer size of the world. An &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octree&lt;/a&gt; could not provide decent collision detection or support for the shadow casting point lights. A &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#beamtrees&quot;&gt;Beam Tree&lt;/a&gt; is not always the best algorithm for visible surface determination, so we provide the &lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#cbuffer&quot;&gt;C-Buffer&lt;/a&gt; as a fallback.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Harmless&lt;/em&gt;&lt;br&gt;
February 3, 2001&lt;/p&gt;
&lt;p&gt;You can contact the author at the following address: &lt;a href=&quot;mailto:harmless@mich.com&quot;&gt;harmless@mich.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also check out his web site at: &lt;a href=&quot;http://www.kmett.com/&quot;&gt;http://www.kmett.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This document is (C) 1999 Edward Kmett and may not be reproduced in any way without explicit permission from the author (Edward Kmett).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2001/harmless-algorithms-4/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Harmless Algorithms — Part 3: Design Patterns And 3D Gaming</title><link>https://comonad.com/reader/2000/harmless-algorithms-3/</link><guid isPermaLink="false">https://comonad.com/reader/2000/harmless-algorithms-3/</guid><pubDate>Wed, 26 Jan 2000 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 26 January 2000&lt;/p&gt;&lt;h2 id=&quot;patterns&quot;&gt;Patterns&lt;/h2&gt;
&lt;p&gt;Certain Design Patterns crop up over and over again in 3d programming. For those of you unfamiliar with Design Patterns, the concept is introduced in the book (imaginatively named) 'Design Patterns' by Gamma et al. (ISBN: 0201633612) The book covers many of the most common design patterns, situations where they are usually applied and their relative strengths and weaknesses. In reading the book, you'll commonly find yourself experiencing small epiphanies as things click into place with your existing experience. Patterns provide a mechanism for talking about the mechanisms used to communicate between objects, ways to reduce redundant code, and generally provide larger building blocks for use in programming.&lt;/p&gt;
&lt;p&gt;Programmers use patterns all the time, simply by applying approaches that worked for previous problems to current problems. A Pattern is simply an attempt to provide nomenclature for something you've been doing all along.&lt;/p&gt;
&lt;h2 id=&quot;templates-and-scalability&quot;&gt;Templates And Scalability&lt;/h2&gt;
&lt;p&gt;I have a passionate dislike of writing the same code multiple times. The major reason I moved to C++ from C was that I could encapsulate common actions in objects and benefit from using higher level primitives to construct my worlds. Unfortunately I still found myself duplicating effort in the interest of efficiency. Then templates came around, don't get me wrong, templates have been around for years, but now support for them (for class level templates anyways) grew ubiquitous enough that I could actually use them without worrying about whether or not my compiler will support this 'cutting edge feature'. Following this was a happy time whereupon I happily rewrote and generalized oodles and oodles of existing code. This affected my code in a landslide fashion.&lt;/p&gt;
&lt;p&gt;Templates generally sit in headers and they are somewhat slower to compile than their hand-written counterparts. As a result, some things that were a nicety before (using large numbers of headers, generally one object to a header) become critical with the adoption of templates on a framework wide scale. People who complain about the compilation speed of templates could do well to get away from the 'kitchen sink' include philosophy promoted by Windows programming (stdafx.h including everything comes to mind) and have each header bring in other headers with just the elements required to compile the elements in the current header. This point is one of many belabored in John Lakos' excellent 'Large Scale C++ Software Design' (ISBN: 0201633620) Other tricks like #pragma once can be used to make small linear gains in compile time, but including only the constructs needed to compile each piece keeps your compilation time from bloating as you add more source files. Unfortunately, I digress.&lt;/p&gt;
&lt;p&gt;Sticking to the design tenets that make code easily extensible can get tricky. There are times when you are tempted to introduce all sorts of circular dependancies which can make your code harder to test in small pieces. Defining an interface is an effort to conceal a great deal of activity behind a stoic facade is tricky the first few times you tackle it and there are 12 wrong ways to do it for every right way. Below is a pattern that I have found to work for my own purposes, I present it here in the hope that it may serve useful to other 3d programmers.&lt;/p&gt;
&lt;h2 id=&quot;the-boilerplate-pattern&quot;&gt;The 'Boilerplate' Pattern&lt;/h2&gt;
&lt;p&gt;In an article on gamespy, Tim sweeney recently attempted to introduce a 'new' concept he wanted in object oriented programming called 'virtual classes'. The pattern I describe below can be used to provide this concept, and is very useful in cases where you need to generate a facade over a wide number of implementations that don't cleanly break down to one-class per implementation. Examples include graphs, a networking layer, your rendering api, and your sound subsystem. In each of these you have multiple related classes nodes and edges, sockets and ports, textures and models, sound snippets, etc that need to perform operations behind the scenes and often need to tie back to managers to actually do things. The java answer to this is to define a series of purely abstract interfaces (black box inheritance) and implement the connections in each set of implementations separately. This approach generally leads to code duplication as each driver has to generate a bunch of boiler plate code. The pattern below shows a way to make a template perform the busy work you usually achieve with cut &amp;amp; paste coding for these 'pure' implementations.&lt;/p&gt;
&lt;p&gt;I call this the 'Boilerplate' pattern, and the first time that I saw this outside of my own code was in the Finite State Machines chapter of 'C++ Gems' by Stanley Lippman. (ISBN: 0135705819) The treatment of this pattern given by 'C++ Gems' is different than mine and if you have trouble with my half-baked code below you may want to pick it up. In fact you may want to pick it up yourself after of course you purchase the Design Patterns book if you have not already done so. This pattern twists the eye and seems deceptively simple the first couple of times you look at it, but without it you can wind up writing a lot of duplicate code.&lt;/p&gt;
&lt;p&gt;I'll attempt to demonstrate with a skeletal interface that could be the start of a rendering API. Obviously in a fully fleshed out rendering API you'd have a lot more methods and probably a lot more classes, meshes, clippers, visibility and occlusion structures come to mind.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;ifndef&lt;/span&gt; INCLUDED_RENDERER&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;define&lt;/span&gt; INCLUDED_RENDERER&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Texture&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;virtual&lt;/span&gt; ~&lt;span class=&quot;hljs-built_in&quot;&gt;Texture&lt;/span&gt;() {}
        &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;makeCurrent&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
};

&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Renderer&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;virtual&lt;/span&gt; Texture * &lt;span class=&quot;hljs-title&quot;&gt;loadTexture&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; * name)&lt;/span&gt;&lt;/span&gt;;
};

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;

Figure &lt;span class=&quot;hljs-number&quot;&gt;1.&lt;/span&gt; renderer.h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All is well and good, given a Renderer, you can ask for a Texture, and have that Texture make itself current. If your Renderer had a set of other operations for rendering polygons and managing matrices, hacking out code to use this interface looks like a straightforward proposition.&lt;/p&gt;
&lt;p&gt;Unfortunately implementing all of your Renderer and Texture classes for different 3d APIs could lead to the onset of repetitive strain injury and if you now have to deal with several duplicate implementations of the behind the scenes linkages between the Texture class and the Renderer. Admittedly in this contrived example we're probably only talking about 3 Implementations so its not so bad, but envision a case where you may have 50-100 implementations, perhaps your monster AI if this all seems like too much work.&lt;/p&gt;
&lt;p&gt;The real evil in cut &amp;amp; paste code comes when you discover a bug. If the code that you cut&amp;amp;pasted in 30 places to manage a linked list leaks memory whenever you delete a node, you may wind up discovering and fixing each of these mistakes as you find them rather than fixing them all at once, simply because you're apt to forget all the locations you pasted the code to, so OOP came around and people started generalizing algorithms and structures and the C++ Standard Library was born, which had all sorts of handy-dandy containers that worked of void*'s to juggle and sort and mangle your objects, these ran afoul of the fact that void*'s could be cast to anything and miscasting is a source of a good deal of bugs. The Standard Template Library implements these algorithms and structures using templates, trading a bit of compiler time for type checking your code.&lt;/p&gt;
&lt;p&gt;Continuing with the example, I'm going to use templates that change who they inherit from based on a passed in parameter. This is a sneaky way to avoid the overhead of writing repetitive proxy code for mixin classes and other such busywork.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;ifndef&lt;/span&gt; INCLUDED_RENDERER_TEMPLATES&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;define&lt;/span&gt; INCLUDED_RENDERER_TEMPLATES&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;renderer.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Baseclass&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Renderer&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;TextureTemplate&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Baseclass {
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt;:
        Renderer * m_renderer;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-built_in&quot;&gt;TextureTemplate&lt;/span&gt;(Renderer &amp;amp; rend, &lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; * name) : &lt;span class=&quot;hljs-built_in&quot;&gt;m_renderer&lt;/span&gt;(&amp;amp;rend), &lt;span class=&quot;hljs-built_in&quot;&gt;Baseclass&lt;/span&gt;(name) { }
        ~&lt;span class=&quot;hljs-built_in&quot;&gt;TextureTemplate&lt;/span&gt;() {
            m_renderer-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;unregisterTexture&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;);
        }
        &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;makeCurrent&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
            m_renderer-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;makeCurrent&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;);
        }
};

&lt;span class=&quot;hljs-keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Baseclass&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;TextureBase&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;RendererTemplate&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Baseclass {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;typedef&lt;/span&gt; TextureTemplate&amp;lt;TextureBase&amp;gt; MyTexture;

        &lt;span class=&quot;hljs-function&quot;&gt;Texture * &lt;span class=&quot;hljs-title&quot;&gt;loadTexture&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; * name)&lt;/span&gt; &lt;/span&gt;{
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;MyTexture&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;,name)
        }
};

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;

Figure &lt;span class=&quot;hljs-number&quot;&gt;2.&lt;/span&gt; renderer_templates.h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we've got 2 classes and 2 templates that don't seem to do anything. The templates lie in a separate header because we don't want to trouble anyone who is just using the interface with templates that are only useful for implementing the interface.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;ifndef&lt;/span&gt; INCLUDED_GLRENDERER&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;define&lt;/span&gt; INCLUDED_GLRENDERER&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;renderer_templates.h&quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;GLTextureImpl&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Texture {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-built_in&quot;&gt;GLTextureImpl&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; * name, blah blah blah) {
            load up texture &lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; opengl...
        }
        &lt;span class=&quot;hljs-keyword&quot;&gt;virtual&lt;/span&gt; ~&lt;span class=&quot;hljs-built_in&quot;&gt;GLTextureImpl&lt;/span&gt;() {}
};

&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;GLRendererImpl&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Renderer {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt;:
        &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;makeCurrent&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(GLTextureImpl &amp;amp; texture)&lt;/span&gt; &lt;/span&gt;{
            ... &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; gl texture stuff here ...
        }
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;unregisterTexture&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(GLTextureImpl &amp;amp; texture)&lt;/span&gt; &lt;/span&gt;{
        ... &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; gl texture stuff here ...
        }

};

&lt;span class=&quot;hljs-keyword&quot;&gt;typedef&lt;/span&gt; TextureTemplate&amp;lt;GLTextureImpl,GLRendererImpl&amp;gt; GLTexture;
&lt;span class=&quot;hljs-keyword&quot;&gt;typedef&lt;/span&gt; RendererTemplate&amp;lt;GLRendererImpl,GLTextureImpl&amp;gt; GLRenderer;

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;

Figure &lt;span class=&quot;hljs-number&quot;&gt;3.&lt;/span&gt; glrenderer.h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The templates are initially a fair chunk of work, but the work pays off as you add implementations by reducing mindless repetitive tasks and letting you focus on real work. The templates do not affect your overall compile time appreciably as they are included only in the individual source files that have to do with implementing your Renderer. You gain implementation while maintaining type safety by sandwiching your code between the templated typed code and the abstract implementation. Inheritance allows you to let calls trickle down the hierarchy and the template allows calls to be made 'up' the hierarchy without the virtual function call overhead.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Interface
    Implementation : public Interface
        TemplateWrapper&amp;lt;Implementation&amp;gt; : public Implementation

Figure 4. Hierarchy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Combined with other patterns like the Singleton and Factory you can reduce the repetitiveness of your code. While this may have perverse effects when a customer or old fashioned manager rates you by lines of code written, it can make for much more maintainable code and gain you the respect and fear of your peers. =)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Harmless&lt;/em&gt;&lt;br&gt;
January 26, 2000&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This document is (C) 1999 Edward Kmett and may not be reproduced in any way without explicit permission from the author (Edward Kmett).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/2000/harmless-algorithms-3/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Harmless Algorithms — Part 2: Scene Traversal Algorithms</title><link>https://comonad.com/reader/1999/harmless-algorithms-2/</link><guid isPermaLink="false">https://comonad.com/reader/1999/harmless-algorithms-2/</guid><pubDate>Fri, 30 Apr 1999 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 30 April 1999&lt;/p&gt;&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This time I want to cover several forms of scene traversal algorithms used to walk through common data structures. For the purposes of this column I will be assuming that the reader is familiar with BSPs and the concept of a portal. Like the fine culling systems overlap with the sorting properties of some of these approaches, some of these will share content with the visibility algorithms in the next installment of this column.&lt;/p&gt;
&lt;p&gt;These algorithms generally require some form of visibility algorithm to be viable for a large scale scene. Some of these provide more information to a visibility algorithm than others; Some provide front-to-back ordering; Some work well in hardware environments; Some work better in software; Some inherently provide their own visibility information through the traversal.&lt;/p&gt;
&lt;p&gt;Next time I will be covering visibility algorithms that work in conjunction with these traversals and the fine culling algorithms from the first column. Like the first one, this column is not meant to stand on its own.&lt;/p&gt;
&lt;p&gt;Note, in the traversals below I have not incorporated the logic to fit the walk to the viewing frustum or to make the traversal obey an occlusion algorithm at all. This will be the subject of the next column.&lt;/p&gt;
&lt;p&gt;This column is primarily intended to enumerate viable alternatives for use in engines for realtime 3d gaming that have worked in my experience. I am not attempting to cover every algorithm extant. I leave that enterprise to some ambitious grad student needing a subject for a dissertation. By no means do I wish to convey the misconception that this column can cover everything of use in 3d graphics. My goal is to point out observations and comparisons between various algorithms and provide alternate methods to a developer stuck in a rut using a given approach.&lt;/p&gt;
&lt;p&gt;Scene Traversals:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bsptrees&quot;&gt;BSP Trees&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bspfrontback&quot;&gt;Planar Front-to-Back&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bspfrontbackleafy&quot;&gt;Leafy Front-to-Back&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#bspquake&quot;&gt;Quake BSP/PVS&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#portals&quot;&gt;Portals&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#portalsrecursive&quot;&gt;Recursive Front-to-Back Traversal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#portalskeyed&quot;&gt;Keyed Queuing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#portalspvs&quot;&gt;Concave/PVS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octrees&quot;&gt;Octrees&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octh&quot;&gt;Hierarchical Front-to-Back Traversal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#octn&quot;&gt;Neighbor Front-to-Back Traversal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#kdtrees&quot;&gt;KD-Tree&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#kdh&quot;&gt;Hierarchical Front-to-Back Traversal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#kdn&quot;&gt;Neighbor Front-to-Back Traversal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#otheralgorithms&quot;&gt;Other Structures&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#feudal&quot;&gt;Feudal Priority Trees&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#adaptive&quot;&gt;Adaptive Octrees&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/#summary&quot;&gt;Summary&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;bsp-trees&quot;&gt;BSP Trees&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;bsptrees&quot;&gt;&lt;/span&gt;A BSP tree is quite frankly one of the most useful data structures out there for 3d graphics. Walking a BSP tree front-to-back is virtually identical to a conventional binary tree's inorder traversal The only difference is the definition of which of the children is the first node to be visited depends upon the sign of the dot product of the viewpoint and the plane normal of the parent node. I will refer to three of the more useful forms of polygon storage in a BSP tree below.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;bspfrontback&quot;&gt;&lt;/span&gt;&lt;em&gt;Planar Front-to-Back:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Planar BSP is what people usually think about when someone mentions a BSP tree. In a planar tree, you can effectively ignore the leaves for rendering purposes. You start with all of your polygons in one bucket, choose one via some heuristic, take that polygon and all polygons that a coplanar to it, create a BSP node, split the rest into two buckets and repeat until you have no polygon lying free in any bucket. Traversal of a Planar BSP from front-to-back is basically a variant on a standard binary tree inorder traversal.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;PlanarBSPNode::planar_ftb&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; Point &amp;amp; point)&lt;/span&gt; &lt;/span&gt;{
     &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;   near = (point dot node.plane_normal &amp;gt;= &lt;span class=&quot;hljs-number&quot;&gt;0.0&lt;/span&gt;);           &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (child[near]) child[near]-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;planar_ftb&lt;/span&gt;(point);           &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each polygon facing the near node in &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt; plane {
         polygon-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;render&lt;/span&gt;()
     }           &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (child[near^&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]) child[near^&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;planar_ftb&lt;/span&gt;(point);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: The 'render' routine for translucent polygons or polygons with transparencies places the polygons on a stack, which is popped away and rendered at the end of the frame.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;bspfrontbackleafy&quot;&gt;&lt;/span&gt;&lt;em&gt;Leafy Front-to-Back:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Leafy BSP is a useful data structure, often used by portal advocates as a quick-and-dirty means to obtain a portal set for arbitrary geometry. In addition to splitting as you walk down the BSP tree you then need to walk back up the BSP tree splitting the contents of the parent planes as you go. Afterwards you can organize the clipped polygon fragments into their assorted leaves. When this is done you no longer track which polygons lie in a given plane of the BSP tree, but instead you track which polygons act as faces for the individual BSP nodes.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;LeafyBSPCommonParent&lt;/span&gt; {
     &lt;span class=&quot;hljs-comment&quot;&gt;// you can do this with typecasting and structs if need be.&lt;/span&gt;
     ....
     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;leafy_ftb&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; Point &amp;amp; point)&lt;/span&gt;&lt;/span&gt;;
}      &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LeafyBSPNode::leafy_ftb&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; Point &amp;amp; point)&lt;/span&gt; &lt;/span&gt;{
     &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;   near = (point dot node.plane_normal &amp;gt;= &lt;span class=&quot;hljs-number&quot;&gt;0.0&lt;/span&gt;);
     child[near]-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;leafy_ftb&lt;/span&gt;(point);
     child[near^&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;leafy_ftb&lt;/span&gt;(point);
}      &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LeafyBSPLeaf::leafy_ftb&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; Point &amp;amp; point)&lt;/span&gt; &lt;/span&gt;{
     &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each polygon that forms a face that faces into &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt; node {
         polygon-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;render&lt;/span&gt;();
     }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;bspquake&quot;&gt;&lt;/span&gt;&lt;em&gt;Quake BSP:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you are using a front-end rasterization routine like passing directly to hardware, an S-Buffer, Active Edge List, or Active Edge Heap, then there is little purpose to splitting the polygons as you walk down the BSP tree. Simply make a second reference to it in the compiler and all is well. If you allow multiple references to a given polygon to float around the tree you can simply adjust the polygon rendering routine to keep a frame index counter like the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Polygon::render&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
     &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (last_seen != frame_no) {
        last_seen = frame_no;
        ...&lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; rendering here...
     }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The walk does not provide front-to-back ordering of the polygons. However in many cases you do not need this. It may cause additional overhead when dealing with translucent polygons (which will need to be sorted back to front). Since this walk will not provide front-to-back ordering in any event, there is little point in doing the scene traversal inorder. Quake gets away with much this same approach, by just taking the nodes from the potentially visible set and throwing their contents down the pipeline at the Active Edge List or openGL hardware.&lt;/p&gt;
&lt;p&gt;In this case, the purpose of the BSP then is to provide convex subregions and to serve as an aid to collision detection. It does not serve any ordering function for visitation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;portals&quot;&gt;Portals&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;portals&quot;&gt;&lt;/span&gt;Before I cover the strengths and weaknesses of given portal traversals, I want to cover the distinction between convex and concave node based portal engines.&lt;/p&gt;
&lt;p&gt;Convex Node:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A convex node engine only allows a convex polyhedron to act as a node. Portals serve to connect individual nodes. Within a convex node engine it is quite possible to get perfect front-to-back ordering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Concave Node:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A concave node engine allows just about anything to serve as a node. It could be a room with some complex geometry, a BSP tree, an undulating mass of procedurally generating flesh, etc... A concave node engine does not lend itself to easily providing front-to-back ordering. As such it is really only suitable to frontend rasterizers such as hardware, S-Buffers, Active Edge Lists and Active Edge Heaps, like the Quake BSP approach above.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With this distinction in mind. I will proceed to the traversals generally used to walk through a conventional portalized scene.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;portalsrecursive&quot;&gt;&lt;/span&gt;&lt;em&gt;Recursive Traversal:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most obvious portal traversal is recursive. The algorithm is generally implemented something like the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Node::visit&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(PortalSilhouette &amp;amp; silhouette)&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (last_seen != this_frame) {
    last_seen = this_frame;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each polygon &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; {
      &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (s-&amp;gt;is_a_portal) {
        Silhouette s = clip polygon &lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; silhouette planes
        next &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; s is empty.
        s-&amp;gt;remote_node-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;visit&lt;/span&gt;(s);
      } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
        Polygon p = clipped polygon &lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; silhouette planes
        p-&amp;gt;&lt;span class=&quot;hljs-built_in&quot;&gt;render&lt;/span&gt;();
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I cannot emphasize enough how poorly this algorithm scales up to higher polygon counts. You may wind up visiting a node several times because you reach it through different nodes, and because of the recursive clipping you may have to render each polygon in multiple discrete fragments. This engine is usually built because it seems to show promise when your engine is just a few rooms. This algorithm is designed to work with convex nodes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;portalskeyed&quot;&gt;&lt;/span&gt;&lt;em&gt;Keyed Queuing:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In an effort to fix the problems with the previous algorihm, another common variant that works if the nodes are obtained from a BSP tree is to use the BSP key for a given node and viewpoint to provide a sorting criteria. This assumes that the data structure used is roughly similar to that for the Leafy BSP above with the addition of portal information for the empty faces shared with neighboring nodes. The concept of sorting by a BSP key is introduced in Michael Abrash's Black Book.&lt;/p&gt;
&lt;p&gt;This walk involves a small binomial heap (priority queue) or sorted list of nodes not yet visited but adjacent to ones visited and visible. The contents of the queue are pulled off in front-to-back order, the nodes are rendered and checked for visible neighbors, which are then placed on the priority queue sorted by their BSP key.&lt;/p&gt;
&lt;p&gt;There are two forms of BSP keys that I have used. One can be generated by walking the BSP tree inorder from a given viewpoint while incrementing a counter at each leaf. The other can be created by walking down the BSP tree towards a given node and by recording as a bitstring every place where the side of the plane the eye resides on differs from the side the given node lies on. Two of these bitstrings can be compared to determine if a given node is nearer to the viewer than the other.&lt;/p&gt;
&lt;p&gt;Note even though this uses a BSP tree for sorting it is technically a portal algorithm because it traverses into its neighbors through the portals. The advantages this holds over Recursive Traversal is that a given node is only rendered once. The disadvantage is the cost of computing the keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;portalspvs&quot;&gt;&lt;/span&gt;&lt;em&gt;Concave/PVS:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The simplest algorithm here for traversal is to allow anything to be in a node and to maintain a potentially visible set between concave nodes. The traversal is identical to the Quake BSP traversal above. Collision can be much harder to detect and handle; Collision detection is very important in a game, so consider this solution with care. Other issues include detecting what node you are presently in in the absence of convex boundaries. Usual fixes include declaring the node to be convex in shape but containing arbitrary geometry. This is a nice fast-and-loose algorithm for getting polygons on the screen though.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for each node in the PVS for the viewpoint {
    node-&amp;gt;render();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One could also use convex nodes for this algorithm which would improve collision detection and may offer other benefits to AI and software rendering, but this still leave determining the current node as a potential problem, if you have no a priori knowledge of the container for a point.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;octrees&quot;&gt;Octrees&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;octrees&quot;&gt;&lt;/span&gt;An octree is a very simple data structure which has recently received a bit more hype than it is worth on its own. There is a decent Introduction to Octrees by Jaap Suter in the tutorial section here on flipCode, so I will not attempt to review that material here. Instead I will build upon it.&lt;/p&gt;
&lt;p&gt;Octrees are very well suited to particular tasks such as finding objects in a given area, or locating likely polygons to attempt collision with; They are not necessarily any better suited to dealing with a static polygon soup than another structure is. By itself an octree does not provide a means of front-to-back traversal of the individual polygons within a leaf, however there are at least two workable front-to-back traversal for walking amongst the nodes themselves.&lt;/p&gt;
&lt;p&gt;Different uses of this structure provide different answers as to what is the best polygon count to stop at when subdividing the octree and what should be used as a maximum recursion depth.&lt;/p&gt;
&lt;p&gt;A common implementation would resemble the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;octree_common&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment&quot;&gt;// note you don't need to store these, you can carry them down with you&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;// as you walk the structure but its easier to demonstrate this way.&lt;/span&gt;
    &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; min_z, max_z, min_y, max_y, min_x, max_x;
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;avg_x&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (min_x + max_x)/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;; }
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;avg_y&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (min_y + max_y)/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;; }
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;avg_z&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (min_z + max_z)/&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;; }

};       &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;octree_node&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; octree_common {
    octree_common * child[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;];
};       &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;octree_leaf&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; octree_common {
    polygon_list polygons;
    object_list  objects;
    ...
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ordering the contents of the octree leaves with miniature BSP trees may be useful if perfect front-to-back ordering of the polygons is desired for another purpose.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;octh&quot;&gt;&lt;/span&gt;&lt;em&gt;Hierarchical Front-to-Back Traversal:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hierarchical traversal of an octree is based on the same plane separation principle that makes a BSP front-to-back walk work. In this case, think of a single node with its eight children as mimicking 3 levels of a BSP tree:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;              z plane
             /       \
      y plane         y plane
     /       \       /       \
x plane  x plane  x plane  x plane
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of the BSP traversals above will then work on the octree just as well as they will on a BSP tree itself. However, observation can simplify some of these traversals. Given which side of the 3 planes subdividing an octree node that the eye point is on you can perform a simpler traversal based on bit toggling. You have three planes and thus 3 sign bits. If you toggle any one bit you will get one of the 3 nodes which share a face with the leaf in question. If you toggle all 3 bits you will get the node in the far corner of the octree. Given this you can simply walk a given octree node from front-to-back by the following sequence.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;octree_node::&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(Point &amp;amp; eye) {
    &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; first      = ((eye.&lt;span class=&quot;hljs-built_in&quot;&gt;x&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-built_in&quot;&gt;avg_x&lt;/span&gt;()) ? &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; : &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) |
                     ((eye.&lt;span class=&quot;hljs-built_in&quot;&gt;y&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-built_in&quot;&gt;avg_y&lt;/span&gt;()) ? &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; : &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) |
                     ((eye.&lt;span class=&quot;hljs-built_in&quot;&gt;z&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-built_in&quot;&gt;avg_z&lt;/span&gt;()) ? &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; : &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);           child[first].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye);           child[first^&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye); &lt;span class=&quot;hljs-comment&quot;&gt;// toggle bit 0 \
    child[first^2].hierarchical_ftb(eye); // toggle bit 1  these 3 can be in any order&lt;/span&gt;
    child[first^&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye); &lt;span class=&quot;hljs-comment&quot;&gt;// toggle bit 2 /&lt;/span&gt;

    child[first^&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye); &lt;span class=&quot;hljs-comment&quot;&gt;// toggle bits 0 &amp;amp; 1 \
    child[first^5].hierarchical_ftb(eye); // toggle bits 0 &amp;amp; 2  these 3 can be in any order&lt;/span&gt;
    child[first^&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye); &lt;span class=&quot;hljs-comment&quot;&gt;// toggle bits 1 &amp;amp; 2 /&lt;/span&gt;

    child[first^&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;].&lt;span class=&quot;hljs-built_in&quot;&gt;hierarchical_ftb&lt;/span&gt;(eye); &lt;span class=&quot;hljs-comment&quot;&gt;// toggle bits 0, 1 &amp;amp; 2&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This walk has the benefit of simplicity. On the other hand it incurs the overhead of walking through the hierarchy for the traversal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;octn&quot;&gt;&lt;/span&gt;&lt;em&gt;Neighbor Front-to-Back Traversal:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Neighbor Traversal requires some minor slight addition to the octree definition:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;octree_common&lt;/span&gt; {
      ...
      &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; last_seen;
      ...
}       &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;octree_leaf&lt;/span&gt; : &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; octree_common {
      ...
      octree_common * neighbors[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;];
      ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These six pointers represent the node that lies adjacent to this leaf through any of its six faces.&lt;/p&gt;
&lt;p&gt;If you are deeper or of equal depth in the tree than the neighbor is then one or many little nodes will point into the same same-sized or larger adjacent node through a common face. If you are at the same height as the neighboring node you will both share the common face on a 1:1 correspondance.&lt;/p&gt;
&lt;p&gt;If you are higher in the tree then your one face will abutt have many leaves_ on the one side of you. This is perfectly acceptable, and in this case you will not attach to the leaf, but to the parent or grandparent node that is at the same height as you in the tree. This is why the links are of an octree_common type xrather than an octree_leaf.&lt;/p&gt;
&lt;p&gt;To traverse from front-to-back through this kind of scene is virtually identical to the Keyed Queuing approach mentioned in the Portal section above. The primary change required is when you link from a leaf to a parent node through a common face, you need to recursively walk down checking the 4 children that share that face's corresponding face for visibility.&lt;/p&gt;
&lt;p&gt;There are some consequences to the modifications that this requires to the data structure. First of all, the neighbor links can become quite onerous to maintain if your octree is rapidly changing. Secondly, your traversal is now complicated by a priority queue and other data structures which may complicate development.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;kd-trees&quot;&gt;KD-Trees&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;kdtrees&quot;&gt;&lt;/span&gt;A KD-Tree is nearly identical to a BSP tree. The differences between a BSP and a KD-tree include that a KD-Tree is forced to use axis aligned planes and the current level of the tree is used to determine which axis to split along.&lt;/p&gt;
&lt;p&gt;A kd-tree node subdivides space into 2 smaller spaces like a BSP node. The additional restrictions upon a kd-tree are that the planes be axis aligned and the choice of axis is based on the current level in the tree.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;              z plane
             /       \
      y plane         y plane
     /       \       /       \
x plane  x plane  x plane  x plane
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a classic kd-tree, and there exist many papers on the subject, off the top of my head Seth Teller uses kd-trees in his paper on visibility determination in densely occluded environments.&lt;/p&gt;
&lt;p&gt;Note that a kd-tree splits on one plane at a time. This allows it to fit better than an octree, because the planes in the children can be at different offsets and because they fit to the data, allowing a relatively balanced structure.&lt;/p&gt;
&lt;p&gt;One modification to the 'classic' kd-tree structure is to allow the choice of plane to split upon to vary at each level, this drives up your preprocessing cost by about a factor of 3, and adds a small bit of data to the tree, but can theoretically produce fewer splits, because you can choose your partitioning plane, by which plane when it would divide the child sets into two equal buckets would produce the fewest splits. Unfortunately this optimization, much like the balance vs. split heuristics in BSP tree generation can lead to degenerately shaped kd-tree nodes if left to run unchecked.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;kdh&quot;&gt;&lt;/span&gt;&lt;em&gt;Hierarchical Front-to-Back Traversal:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hierarchical traversal of a kd-tree is identical to hierarchical traversal of an octree as described above or to a front-to-back traversal of a BSP tree.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;kdn&quot;&gt;&lt;/span&gt;&lt;em&gt;Neighbor Front-to-Back Traversal:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Neighbor traversal of a kd-tree can be performed in a similar manner to the neighbor traversal of the octree above, but it is not as effective. The reason is because the faces of the octree children at a given level all line up perfectly. In the kd-tree using the figure above, the two y aligned planes are likely to have chosen different offsets to split upon. This means that the neighbor traversal winds up severely handicapped as the traversal algorithm has to walk down to the leaf from a higher level node as the norm rather than the exception, unlike the octree neighbor traversal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;other-algorithms&quot;&gt;Other Algorithms&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;otheralgorithms&quot;&gt;&lt;/span&gt;&lt;span id=&quot;feudal&quot;&gt;&lt;/span&gt;&lt;em&gt;Feudal Priority Trees:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span id=&quot;feudal&quot;&gt;&lt;/span&gt;A feudal priority tree is a form of dynamic BSP tree suited to low polygon count environments. It has more relaxed requirements than a conventional BSP tree, but the runtime cost of using it can be much higher, and it doesn't scale well.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.scs.ryerson.ca/h2jang/archive-19980507.html&quot;&gt;http://www.scs.ryerson.ca/h2jang/archive-19980507.html&lt;/a&gt; contains a brief description and includes the names of several papers on the subject.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span id=&quot;adaptive&quot;&gt;&lt;/span&gt;&lt;em&gt;Adaptive Octrees:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An adaptive octree is an octree which allows the position of the split point in the center of an octree node to be displaced. In practice, I tend to prefer a kd-tree to an adaptive octree, but in some cases, the adaptive octree may consume less memory. In addition, the neighbor front-to-back traversal of an adaptive octree tends to be faster than for a kd-tree, because within a given octree node the partitioning planes line up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In summary, if you are writing a hardware only engine, a concave node based portal engine is probably a safe bet. The vagaries involved in collision in this environment can be overcome. The only real difficulty is that given an arbitrary object in 3d space, it can be a bit expensive to discover which nodes the object is touching, without tracking this information as the object moves around the level.&lt;/p&gt;
&lt;p&gt;Octrees and kd-trees serve as a spatial subdivision mechanism, in and of themselves they cannot perform all polygon sorting, and in fact, on hardware you do not need polygon sorting except for surfaces with translucencies.&lt;/p&gt;
&lt;p&gt;Next time, I will be covering methods for visibility that combine structures from both this and the previous issue.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Harmless&lt;/em&gt;&lt;br&gt;
April 29, 1999&lt;/p&gt;
&lt;p&gt;You can contact the author at the following address: &lt;a href=&quot;mailto:harmless@bloodshed.com&quot;&gt;harmless@bloodshed.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also check out his web site at: &lt;a href=&quot;http://www.bloodshed.com/&quot;&gt;http://www.bloodshed.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This document is (C) 1999 Edward Kmett and may not be reproduced in any way without explicit permission from the author (Edward Kmett).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-2/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Harmless Algorithms — Part 1: Fine Occlusion Culling Algorithms</title><link>https://comonad.com/reader/1999/harmless-algorithms-1/</link><guid isPermaLink="false">https://comonad.com/reader/1999/harmless-algorithms-1/</guid><pubDate>Fri, 09 Apr 1999 12:00:00 GMT</pubDate><category>Article</category><description>&lt;p&gt;Edward Kmett · 9 April 1999&lt;/p&gt;&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The first thing that I want to discuss are the various forms of fine occlusion culling algorithms out there. Fine occlusion culling is the process of separating actually visible polygons from a predetermined potentially visible set. These algorithms do not generally offer any order of magnitude speed increase to an average engine in and of themselves, however some of them do provide tools useful to more general algorithms and visibility structures.&lt;/p&gt;
&lt;p&gt;I am assuming at this point that the reader is at least generally familiar with a BSP tree's sorting properties, what a portal is, and is capable of rasterizing their own polygons or of using a 3d hardware API such as Glide, OpenGL or Direct3d. I also assume at least passing familiarity with linked lists, binary trees, and other conventional data structures and algorithms.&lt;/p&gt;
&lt;p&gt;The use of floats throughout here is intentional for subpixel accuracy and ease of reading, if you prefer fixed points so be it.&lt;/p&gt;
&lt;p&gt;The algorithms that will be covered here are the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#sbuffer&quot;&gt;S-Buffers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#bst&quot;&gt;Binary Span Trees (BST)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#cbuffer&quot;&gt;C-Buffers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#ael&quot;&gt;Active Edge Lists (AEL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#aeh&quot;&gt;Active Edge Heaps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#triage&quot;&gt;Triage Masks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/#beamtrees&quot;&gt;Beam Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;s-buffers&quot;&gt;S-Buffers&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;sbuffer&quot;&gt;&lt;/span&gt;The s-buffer algorithm is described in Paul Nettle's s-buffer FAQ, and is a good starting place for looking at fine occlusion culling.&lt;/p&gt;
&lt;p&gt;A classic s-buffer span-converts a polygon into a list of line segments. You have 1 bucket per scanline, and in that scanline you maintain a structures or class for an individual span which generally looks like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;classic_sbuffer_span&lt;/span&gt; {
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_x;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; end_x;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_ooz; &lt;span class=&quot;hljs-comment&quot;&gt;// 1/z, d(1/z)/dx&lt;/span&gt;

      ...              &lt;span class=&quot;hljs-comment&quot;&gt;// gradient setup for u and v, etc&lt;/span&gt;

      classic_sbuffer_poly * poly;
      classic_sbuffer_span * next;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In your poly object you contain information that is invariant over the entire poly (i.e. d(1/z)/dx, d(1/z)/dy) and as you insert spans into the buffer you clip against existing spans. How this is done depends on whether or not you can depend on the polygons going into the sbuffer to be sorted or not.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Interpenetrating Version:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given the truly general case, which would allow for interpenetrating spans and spans being inserted out of order, your inner loop for inserting a given span not only has to look for what spans your introduced polygon overlaps, but whether the interpolated 1/z regions overlap, and if they do, if the intersection is on or off of the existing span and the inserted span. The number of special cases you need to handle in your inner insertion loop can grow prohibitive. Also since you can later occlude a polygon that seemed like it was going to be in front, you have to do all of your rendering in a post process or you risk unnecessary overdraw.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Non-Interpenetrating Version:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given the slightly less general case of assuming that there are no interpenetrating while still inserting spans out of order, you can handle most static worlds. Your inner loop simplifies tremendously compared to the more general algorithm.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Immediate Rendering Version:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Next option. Instead of storing the gradient information, or for that matter any information about the polygon in a span other than its starting and ending x position, and its starting z and d(1/z)/dx, you can make the assumption that whatever is feeding you polygons is doing so in a 'roughly' front to back order. If this is the case you can render each span when you clip it. This greatly shrinks the size of the individual span structures (to less than the size of a Pentium cache line) which can improve your performance quite significantly. Now you no longer have a second pass through a fairly large data structure, but you risk some overdraw in the case of an imperfectly sorted scene and software rendering. This algorithm also has the advantage that it renders in a texture coherent fashion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This data structure looks more like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;immediate_sbuffer_span&lt;/span&gt; {
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_x;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; end_x;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_ooz;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; doozdx;
      immediate_sbuffer_span * next;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;binary-span-trees&quot;&gt;Binary Span Trees&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;bst&quot;&gt;&lt;/span&gt;Tom Hammersley devised this algorithm and used to have a detailed description and source code up on his now non-existant website. The span tree is very similar to the classic binary search tree algorithm.&lt;/p&gt;
&lt;p&gt;The first assumption made is that all polygons will be coming to this algorithm in presorted order as from a conventional BSP tree or a recursive portal engine.&lt;/p&gt;
&lt;p&gt;Now you can only handle input that comes in perfect front-to-back order. Certain portal algorithms and BSP key sorting can provide this, but generally they do not provide this for dynamic actors. This generally means that dynamic objects have to be moved off into another stage of the pipeline in order to use this algorithm. This is not necessarily a bad thing depending on the purpose for the engine in question.&lt;/p&gt;
&lt;p&gt;Dynamic objects would then need to be z-buffered in, or clipped and then inserted into the BSP before this stage. For hardware, inserting all of the objects which are in visible BSP nodes directly into the zbuffer is generally the most expedient approach.&lt;/p&gt;
&lt;p&gt;The fundamental change is switching to a binary tree based structure:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;bst_span&lt;/span&gt; {
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_x, end_x;
      bst_span * next, * prev;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Insertions clip their way down the tree. If you are lucky, the tree may reduce the number of spans visited as you clip your node.&lt;/p&gt;
&lt;p&gt;Relative to the more general s-buffer algorithm above, its primary speed up comes from the assumption of front-to-back order reducing the amount of clipping, than from any gains made by the tree itself.&lt;/p&gt;
&lt;p&gt;The problems I see with this algorithm is that its really just not seeing the forest for the trees. (no pun intended) In general, the goal of this algorithm, that is, the reduction of the number of spans visited during the clipping and display of a given span is valid, but I have found that in practice (for me) a simpler algorithm (the c-buffer algorithm which follows) gives better results.&lt;/p&gt;
&lt;p&gt;An additional trait that is important in several of these algorithms, that this approach provides, is the ability to check if a polygon silhouette would be visible (span convert the polygon as if you were going to insert into the tree, quit when you get your first visible sub span). You can perform this operation on the s-buffer algorithms above, but not without a great deal of z computations.&lt;/p&gt;
&lt;h2 id=&quot;c-buffers&quot;&gt;C-Buffers&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;cbuffer&quot;&gt;&lt;/span&gt;What I dubbed a coverage buffer (c-buffer for short) is another constrained variant on the s-buffer algorithm. Again, like the Binary Span Tree we will make the assumption that you can get your polygons to this stage of the pipeline in BSP front-to-back order.&lt;/p&gt;
&lt;p&gt;Your span definition shrinks to:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;cbuffer_span&lt;/span&gt; {
    &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; start_x, end_x;
    cbuffer_span * next;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then walk left to right through the linked list per scanline. As you walk if you clip on an existing node, congeal with it by just lowering its minimum x value or raising its maximum x value, if you are clipped on both sides, remove the second node, and expand the first one to its end boundary&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Example 1
  Poly to draw         -------------|XXXXXXXXXXXX|-----------
  Existing Span        -----|XXXXXXXXXXXX|-------------------
  Rendered portion     ------------------|XXXXXXX|-----------
  New Span in cbuffer  -----|XXXXXXXXXXXXXXXXXXXX|-----------    Example 2
  Poly to draw         ---------|XXXXXXXXXXXX|---------------
  Existing Spans       ------|XXXXX|------|XXXXXX|-----------
  Rendered Portion     ------------|XXXXXX|------------------
  New Span in cbuffer  ------|XXXXXXXXXXXXXXXXXXX|-----------    Example 3
  Poly to draw         ---|XXXXXXXXXXXXXXXXXX|---------------
  Existing Spans       ------|XXXXX|------|XXXXXX|-----------
  Rendered Portions    ---|XX|-----|XXXXXX|------------------
  New Span in cbuffer  ---|XXXXXXXXXXXXXXXXXXXXXX|-----------
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that examples 2 and 3 actually reclaimed a span data structure for use in later spans. As the screen fills up the coverage buffer, this algorithm actually lowers the number of spans in circulation, thus improving performance. The reason that it works is because with perfect front-to-back ordering, you do not care about the z information at all in the span buffer; you simply need to know the portions of the screen which have been covered. You know by definition of a bsp tree that the portions already rendered cannot be concealed by polygons further away in the tree. Render the portions as you walk the span buffer, and clip your polygon fragment. This way you do not need to retain any of the clipped values in the span buffer because you have already rendered them and filled in your z-buffer if you so choose.&lt;/p&gt;
&lt;p&gt;Notice also that now there is no longer a correlation between the number of spans and the call to the rasterization routine, yet you still retain a single draw per pixel. When the scene is filled, you end up with a single fragment per scanline.&lt;/p&gt;
&lt;p&gt;This algorithm also shares the desirable quick would-this-polygon-be-visible test as the Binary Span Tree above.&lt;/p&gt;
&lt;p&gt;A variant proposed by Chris Babcock:&lt;/p&gt;
&lt;p&gt;In practice it is better to start with one span per scanline, and redefine your spans to be areas where there are no polygons. In this case you start with one span and converge an empty list by eating away pieces of it.&lt;/p&gt;
&lt;p&gt;Here's the &quot;is visible&quot; test for this variant:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;test_visible&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(cbuffer_line &amp;amp; line,&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; start_x,&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; end_x)&lt;/span&gt; &lt;/span&gt;{
     cbuffer_span *scan = line.spans;
     &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (scan) {
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (end_x &amp;lt;  scan-&amp;gt;start_x) &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (start_x &amp;lt;= scan-&amp;gt;end_x) &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
        scan = scan-&amp;gt;next;
     }
     &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;active-edge-lists-ael&quot;&gt;Active Edge Lists (AEL)&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;ael&quot;&gt;&lt;/span&gt;There are at least two very good descriptions of this algorithm floating around in Michael Abrash's Black Book (I can't recall if it was in the earlier Zen of Graphics Programming) and in Computer Graphics: Principles and Practice; because of this, I will just summarize the algorithm's relative strengths and weaknesses. An AEL allows insertion of the polygons in any order, but requires a two-pass walk since you have to build up the data structure and then afterwards you walk across the screen in a scanline coherent order while drawing.&lt;/p&gt;
&lt;p&gt;Its strength resides in the fact that it scales better to higher resolutions than most of the algorithms above for software. Just like the first arbitrary order s-Buffer variants above, you can throw any old polygon at it and this stage of the pipeline will not choke.&lt;/p&gt;
&lt;p&gt;Unfortunately it renders in a scanline coherent manner, which generally causes a speed hit because almost all of your texture accesses are incoherent. Also, the two-stage rendering structure means you wind up building up the structure, having it go out of cache while you walk the scene and then have to walk through it all over again.&lt;/p&gt;
&lt;p&gt;Other concerns include that there are many data structures built up here, a linked list per scanline of edges that begin and end, a structure representing all of the information needed to rasterize a given polygon, and then the sorted list of edges that you use as you walk across the scanline, and the small list of polygons that overlap the current pixel. Each one unto themselves is fairly minor, but it does add significant complexity to an implementation.&lt;/p&gt;
&lt;p&gt;This algorithm does not possess a corollary to the visible polygon test, which means that every potentially visible polygon needs to be inserted into the structure that is walked in the second stage. Depending on how conservative of a set your gross culling and occlusion algorithm is this may or may not be a problem (Witness quake which uses this algorithm).&lt;/p&gt;
&lt;h2 id=&quot;active-edge-heaps-aeh&quot;&gt;Active Edge Heaps (AEH)&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;aeh&quot;&gt;&lt;/span&gt;This is an algorithm I used briefly in a software rendering engine that I found useful enough to relate. Its goal was to address the number of data structures floating around in the Active Edge Table algorithm above by using a binomial heap.&lt;/p&gt;
&lt;p&gt;Like the AEL approach above, this algorithm does not require front to back sorting, nor does it even gain anything from it.&lt;/p&gt;
&lt;p&gt;For those not familiar with a binomial heap, I refer you to any of Robert Sedgewick's books on Algorithms (or for that matter almost any Algorithm text). A binomial heap is also known as a priority queue, and is used for the heap sort.&lt;/p&gt;
&lt;p&gt;A heap is a form of binary tree that is always packed in memory (which is very good for cache coherence). The basic change is to use either an xy pair or a screen coordinate as a key for a node in the binomial heap. Initialize each edge with the position along each edge at its top y coordinate.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;aeh_edge&lt;/span&gt; {
      &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; type;  &lt;span class=&quot;hljs-comment&quot;&gt;// start or end of a span - 1 or -1.&lt;/span&gt;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; x, ooz;
      &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; y, last_y;
      &lt;span class=&quot;hljs-type&quot;&gt;float&lt;/span&gt; dxdy, doozdx, doozdy;
      aeh_poly * poly;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One property provided by a binomial heap is the ability to quickly extract the entry with the highest priority (or lowest key). Using the key as the current xy value of a given entry, you will automatically start on the top scanline with the beginning of the first span by extracting the top node of the heap.&lt;/p&gt;
&lt;p&gt;pseudo-code:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (heap isnt empty) {
    look at node at top of heap
       &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; its the start of an edge add poly to the list of current spans.
       &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; remove poly from the list of current spans.             increase y, &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; its less than last_y then
       add dxdy &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; doozdy to the x &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; ooz values &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;reinsert&lt;/span&gt; (you can
       quickly reinsert the top node of a binomial heap by decreasing its
       priority &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; then verifying the heap sorting property.)             draw from the coordinate stated to the node at the top of the heap.
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are fewer data structures than in the case of an AEL. You no longer have the separate buckets per scanline for insertion and deletion of nodes on each pass. The initial insertion cost of each of the edges is higher than for an AEL and you are still stuck with a two-pass data structure. On the other hand, you aren't stuck iterating through the list of active edges for every scanline to insert and delete each one that begins or ends on a given scanline.&lt;/p&gt;
&lt;p&gt;I present this algorithm as an example of the trade-offs involved in different approaches. This lacks a quick polygon visibility just test like the Active Edge Table method above unfortunately does.&lt;/p&gt;
&lt;h2 id=&quot;triage-masks&quot;&gt;Triage Masks&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;triage&quot;&gt;&lt;/span&gt;Ned Greene of Apple published a very interesting and &lt;a href=&quot;http://www2.bloodshed.com/cgi-bin/pm.cgi?filename=greene96.ps&amp;page=db&quot;&gt;often overlooked paper&lt;/a&gt; on the subject of a variant on Warnock's algorithm (quadtree subdivision of the view) that used what he called triage masks. Rather than present his work here, I'll simply provide a &lt;a href=&quot;http://www2.bloodshed.com/cgi-bin/pm.cgi?filename=greene96.ps&amp;page=db&quot;&gt;pointer&lt;/a&gt; to the original document, a brief overview, and compare and contrast it with the other algorithms above.&lt;/p&gt;
&lt;p&gt;Triage mask are a hierarchial form of coverage buffering that uses binary bit operations to check for occlusion or probable occlusion. In his paper, Ned Greene used 8x8 masks which required 64 bit binary operations. The intersection or union of 3 or more masks provides the silhouette at a given depth of this hierarchial occlusion structure. In short the triage mask data structure enables you to quickly evaluate if a polygon is visible or not with a few binary operations, and if the resolution of that query is insufficient to find out what subcels you need to zoom in on and evaluate to determine whether or not the polygon is visible.&lt;/p&gt;
&lt;p&gt;The requirements are the same as for the Binary Span Tree and for the C-Buffer: Perfect front to back presorting.&lt;/p&gt;
&lt;p&gt;The good part of this algorithm is that as your scene fills up you can quickly reject whole polygons with a handful of binary operations.&lt;/p&gt;
&lt;p&gt;Problems include that the preprocess of generating the masks is easy to mess up and I haven't yet found a way to do the edge of cel intersections as fast as I'd like to. Scaling up in multiples of 8x8 is somewhat scary, given your virtual screen resolutions for this go from 8x8 to 64x64 to 512x512 to 4096x4096, and while that is reassuring for future video resolutions, under 1024x768 or so this algorithm seems to be, for me, a net loss.&lt;/p&gt;
&lt;p&gt;This algorithm supplies a very good spot checked polygon visibility test.&lt;/p&gt;
&lt;h2 id=&quot;beam-trees&quot;&gt;Beam Trees&lt;/h2&gt;
&lt;p&gt;&lt;span id=&quot;beamtrees&quot;&gt;&lt;/span&gt;Unlike the rest of the algorithms above, this algorithm takes place in object space. This means that you can get away cheaper on the polygons that you do not display. Another concern not addressed by the methods above is the matter of subpixel accuracy and conservative estimation. This algorithm is also applicable for shadow casting light sources, but that is another topic for another day.&lt;/p&gt;
&lt;p&gt;A beamtree, as I describe herein, should really be thought of as a 3 dimensional structure. It really is just a specialized form of BSP tree. In a beamtree all planes pass through the origin (the eye point). Other than that it subdivides the view as you walk from front to back through the scene into drawn and undrawn sections, much like a solid BSP can divide between solid portions of the map and air. Since all planes pass through the origin, their 'd' component is always 0, which means you do not need to normalize the planes during beamtree generation because when you use the distances from the plane for linear interpolation, the magnitude of the plane 'normal' is irrelevant and cancels itself out.&lt;/p&gt;
&lt;p&gt;In short, the plane passing through two points in the scene and the origin is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;plane' = (v1-eye) cross (v2-eye)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then to get the side of that plane any point is on:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;side = the sign of ((vertex-eye) . plane')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a given viewpoint, the beamtree is used by putting in place 4 'slabs' representing the left, right, top and bottom of the viewing frustum.&lt;/p&gt;
&lt;p&gt;This gives you a degenerate tree like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    left
   /    \
solid   right
        /    \
    solid    top
             /  \
         solid  bottom
                /    \
             solid   open
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above use of an arbitrary plane and its opposite is necessary, because otherwise the first plane you inserted into the beamtree would cause half of the field of view from the light source to fall into shadow.&lt;/p&gt;
&lt;p&gt;When you insert a polygon, you walk down the beamtree with all of the points in your polygon, visiting each side that the points lie on.&lt;/p&gt;
&lt;p&gt;You do not need to define the leaf nodes. Anything that opens to an empty 'left' child is solid anything opening to an empty 'right' child is open and unrendered. so think of left and right as 'drawn/undrawn' or vice versa.&lt;/p&gt;
&lt;p&gt;Your recursive insertion routine would look something like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;cpp code&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;define&lt;/span&gt; EPSILON 1.0e-6     int convervative_signof(float value) {&lt;/span&gt;
     &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; result;
     &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (value &amp;lt; -EPSILON) &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;
     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (value &amp;gt; EPSILON) &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;;
     &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
}     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;recursive_insertion&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(vertex * fragment, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nvertices, beamtree_node &amp;amp; node)&lt;/span&gt; &lt;/span&gt;{
     &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; sign=&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, * signs = (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; *)&lt;span class=&quot;hljs-built_in&quot;&gt;alloca&lt;/span&gt;(nvertices*&lt;span class=&quot;hljs-keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;));
     &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i=&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;i&amp;lt;nvertices;++i) {
         sign |= signs[i] = &lt;span class=&quot;hljs-built_in&quot;&gt;conservative_signof&lt;/span&gt; (fragment[i] dot node.plane);
     }
     &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (sign == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
         &lt;span class=&quot;hljs-comment&quot;&gt;// generally you just throw these away as terminating on a solid node.&lt;/span&gt;
     } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (sign == &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) {
         &lt;span class=&quot;hljs-built_in&quot;&gt;right_attach&lt;/span&gt;(fragment,nvertices,node);
     } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (sign == &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;) {
         &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (node-&amp;gt;left) {                  in here find the contiguous set of vertices that have a
             conservative_signof of all &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;'s and 1'&lt;/span&gt;s, passing along any
             &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;'s that precede or follow a beginning or final 1. this
             needs to wrap around to the beginning of the set as well.                  recursive_insertion(the set, # of verts, *node-&amp;gt;left);
        } else {
             // throw it away as terminating on a solid node
        }             out here find the contiguous set of vertices that have a
        conservative_signof of all 0'&lt;/span&gt;s &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;'s, and along any 1'&lt;/span&gt;s
        that precede &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; follow a beginning &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2.&lt;/span&gt;             &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (node-&amp;gt;right) {
            &lt;span class=&quot;hljs-built_in&quot;&gt;recursive_insertion&lt;/span&gt;(the set, &lt;span class=&quot;hljs-meta&quot;&gt;# of verts, *node-&amp;gt;right);&lt;/span&gt;
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
            &lt;span class=&quot;hljs-built_in&quot;&gt;right_attach&lt;/span&gt;(the set, number of vertices in the set, node);
        }
     }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;right_attach takes the edges between the supplied vertices and inserts them as planes using the equation given on the right hand side of the current plane.&lt;/p&gt;
&lt;p&gt;In short, when you recurse to a solid node you throw away that fragment because its occluded.&lt;/p&gt;
&lt;p&gt;When you recurse to an open node, you take all edges of the polygon that have a point that has recursed this far and insert those edges as solid planes, the consistency of your clockwise or counterclockwise winding will orient the plane to maintain the proper sidedness relationship.&lt;/p&gt;
&lt;p&gt;Any polygon that requires you to modify the tree is visible.&lt;/p&gt;
&lt;p&gt;You can give the eye a 360 degree frustum with the following trickery:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;      plane
      /   \
   -plane  open
    /  \
solid   open
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don't start with some arbitrary plane, the first plane being inserted at the root would occlude half the surfaces from the standpoint of the light.&lt;/p&gt;
&lt;p&gt;Relative to the rest of the algorithms above, this approach is least likely to run afoul of pixel sized gaps due to scan conversion problems.&lt;/p&gt;
&lt;p&gt;If you are looking for similar algorithms to compare with, this is very similar to Naylor's algorithm for performing CSG with a BSP tree and a B-rep.&lt;/p&gt;
&lt;p&gt;This algorithm provides a polygon visibility test, its not as fast as the triage or cbuffer polygon visibility test, but it has the potential to avoid a lot of scan conversion problems that affect the other algorithms.&lt;/p&gt;
&lt;p&gt;I will be supplying tricks to collapse a beamtree in manners similar to the cbuffer algorithm, when I get around to talking about lighting.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;These algorithms do not in-and-of-themselves solve visibility problems; they are merely ways to take polygons from a pretty good guess of what is visible and determine if they are indeed visible. When combined with some on-the-fly gross culling/vis system they can be used to build a viable engine. Next time I'll review some of the various visibility systems, which of these that they will work with, and the relative merits and flaws of each.&lt;/p&gt;
&lt;p&gt;Indeed all of the algorithms above can potentially run afoul of problems when used in conjunction with hardware; if your edge conversion doesn't exactly correspond with the algorithm used by the graphics card you may wind up with fragments of polygons that your algorithm says aren't visible. The beamtree avoids one stage in which this error usually crops up, but it doesn't shrink as polygons are added as does the cbuffer algorithm.&lt;/p&gt;
&lt;p&gt;Which of these you use (or if you use another) should probably be determined by what gross culling and visibility determination algorithm you are using and whether or not you are writing for hardware, software, or a hybrid game engine.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Harmless&lt;/em&gt;&lt;br&gt;
April 8, 1999&lt;/p&gt;
&lt;p&gt;You can contact the author at the following address: &lt;a href=&quot;mailto:harmless@bloodshed.com&quot;&gt;harmless@bloodshed.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also check out his web site at: &lt;a href=&quot;http://www.bloodshed.com/&quot;&gt;http://www.bloodshed.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This document is (C) 1999 Edward Kmett and may not be reproduced in any way without explicit permission from the author (Edward Kmett).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1999/harmless-algorithms-1/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Wavelets in 3D Graphics</title><link>https://comonad.com/reader/1995/wavelets-in-3d-graphics/</link><guid isPermaLink="false">https://comonad.com/reader/1995/wavelets-in-3d-graphics/</guid><category>Article</category><description>&lt;p&gt;Edward Kmett · Circa 1995&lt;/p&gt;&lt;p&gt;Wavelets have become a hot topic in mathematics in general and computer graphics in particular. They are a useful tool for multiresolution analysis of a data set and for data compression. There are several popular wavelet basis and scaling functions. Herein I will focus on the Haar wavelet basis and its application to compression of low contrast textures in a 3d polygonal game engine that I am developing. In this application, I exploit both of these characteristics of the Haar basis.&lt;/p&gt;
&lt;h2 id=&quot;terminology&quot;&gt;Terminology&lt;/h2&gt;
&lt;p&gt;For the purposes of this article, a texture consists of a 32 bit image, 2&lt;sup&gt;n&lt;/sup&gt; texels wide, 2&lt;sup&gt;n&lt;/sup&gt; texels tall. A texel is an industry buzzword for a pixel of the texture before it is projected onto the screen. Mipmaps are also stored for each image. Each mipmap is a power of two smaller than the last and is generated by antialiasing from the previous image. So the mipmap set for a 128x128 texture would be 64x64, 32x32, 16x16,8x8,4x4,2x2 and 1x1. Typically, the lowest 3 or 4 mipmap levels are more hassle to maintain than they are worth and are often omitted since for a game one can often constrain the scene to keep polygons that are that far away from being visible. Also, if they are visible, you probably have bigger problems with the sheer number of small polygons you need to project and display than worrying about a little aliasing problem in the distance. Storing the mipmaps drives up texture storage requirements by 1/3rd.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;A typical texture size is 256x256. At 4 bytes per texel this single image consumes 256Kb of RAM per texture. A practical scene has approximately a dozen textures visible at a time, and up to a hundred distributed around the map in places where they are not immediately visible. To keep everything loaded at all times would require approximately 200Mb of memory just for the texture and mipmap data, let alone any game logic, lightmapping or geometry. Needless to say, at this time expecting that much memory from a typical end user's i computer is unreasonable.&lt;/p&gt;
&lt;h2 id=&quot;possible-solutions&quot;&gt;Possible Solutions&lt;/h2&gt;
&lt;p&gt;One solution is to reduce the images to 8 bit palettized representations. This reduces memory requirements to about 50Mb, which can be reasonably swapped to and from disk if you can exploit coherence in the way textures are distributed around the map. However, if you cannot take advantage of any spatial coherence or caching then you will experience a stutter caused by the sudden hit of having to go look up the texture to continue rendering the display.   This stutter has a very negative psychological effect; As a player, you are suddenly reminded that you are playing a game and the sense of immersion goes out the window. Frame rate consistency is more important over all than the best case performance, so a performance leveling factor is required.   The stutter is aggravated by the fact that in order to swap textures the engine has to look to disk, which is several orders of magnitude slower than accessing the texture directly from memory. Also, a paletted representation of textures requires you to use a smaller subset of colorspace to store the image, you tend to lose a lot of quality in the conversion, and even reconstructed, if you are using a standard palette with six bit color components, the reconstructed texel is at best 18 bits upon reconstruction. Other complications arise when you want to store an alpha (translucency) channel in a paletted representation.&lt;/p&gt;
&lt;p&gt;Another option is to store a compressed representation of the texture in memory and to derive the mipmaps from that. The problem with this approach is that you are stuck decompressing the entire texture and then extracting all mipmap levels even if you only needed the 32x32 mipmap from a 256x256 texture. Typically, you will need the lower mipmaps before the larger mipmaps for a given texture.  This is intuitive since as you walk through a scene, surfaces will come into view in the distance and get closer. As they approach, they will gradually need more detail (higher mipmap levels). With this approach you have to take the full hit all at once. This introduces stutter. JPEG style compression can be used to good effect, you can typically obtain a higher compression ratio than by using the approach I took below. Unfortunately, its all or nothing nature makes it ill suited to my needs. Also, the better compression comes at the cost of having to perform the inverse DCT on each 8x8 block of the image. This process takes 54 multiplications, 462 additions and 6 shifts per channel using Feig's method, which is presently the most efficient published method on Intel processors. In comparison the same 8x8 block decompresses with 256 additions per channel using Haar.&lt;/p&gt;
&lt;h2 id=&quot;an-overview-of-the-haar-basis&quot;&gt;An overview of the Haar Basis&lt;/h2&gt;
&lt;p&gt;This is intended to supply an intuitive understanding of how the Haar basis works. What follows is not intended as a rigorous mathematical proof or examination of the subject.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Given 2^n samples such as:                    { 11, 1, 1, 7 }
Pair samples and average them giving:         { (11+1)/2, (1+7)/2 } = { 6, 4 }
Repeat until you have 1 value:                { (6+4)/2 } = { 5 }
&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;wavelet-diagram&quot; id=&quot;haar-figure-1&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/haar-averaging.svg&quot; alt=&quot;The samples 11, 1, 1, 7 average in pairs to 6 and 4, then to the scaling value 5.&quot; width=&quot;440&quot; height=&quot;235&quot;&gt;&lt;figcaption&gt;Figure 1. Pairwise averages and the scaling value.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This value at the top of this tree (Figure 1) is your scaling value.&lt;/p&gt;
&lt;p&gt;Now, you recurse down the hierarchy that you paired. At each level you subtract value in the right hand child of the current node from the value in the current node.  Do not recurse into the leaf nodes on the tree.&lt;/p&gt;
&lt;figure class=&quot;wavelet-diagram&quot; id=&quot;haar-figure-2&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/haar-coefficients.svg&quot; alt=&quot;A coefficient tree with 1 at level 0, and 5 and minus 3 at level 1.&quot; width=&quot;440&quot; height=&quot;160&quot;&gt;&lt;figcaption&gt;Figure 2. Wavelet coefficients by level.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;There are 2&lt;sup&gt;n&lt;/sup&gt; values in a given level of the tree.  These values are your wavelet coefficients.   With these values you can reconstruct the original sample set since this operation is invertible.&lt;/p&gt;
&lt;p&gt;There are 2&lt;sup&gt;m&lt;/sup&gt; coefficients at the mth level of the hierarchy. Adding the scaling value to this set, provides the sample number of values as the original data set, however when converted into Haar form, the numbers are now indicative of the changes from the smaller level.&lt;/p&gt;
&lt;p&gt;Reconstruction is straightforward. Start with the scaling value and the coefficient for level 0. Add the coefficient to the scaling value to generate the left hand child, subtract it from the scaling value to generate the right hand child. Take those nodes and repeat down the tree:&lt;/p&gt;
&lt;figure class=&quot;wavelet-diagram&quot; id=&quot;haar-figure-3&quot;&gt;&lt;div class=&quot;wavelet-reconstruction&quot;&gt;&lt;img src=&quot;https://comonad.com/figures/haar-reconstruction.svg&quot; alt=&quot;An expression tree starting at 5, then 5 plus 1 and 5 minus 1, then 6 plus 5, 6 minus 5, 4 plus negative 3, and 4 minus negative 3.&quot; width=&quot;440&quot; height=&quot;235&quot;&gt;&lt;span class=&quot;wavelet-equals&quot; aria-label=&quot;equals&quot;&gt;=&lt;/span&gt;&lt;img src=&quot;https://comonad.com/figures/haar-averaging.svg&quot; alt=&quot;The evaluated tree: 5, then 6 and 4, then the recovered samples 11, 1, 1, 7.&quot; width=&quot;440&quot; height=&quot;235&quot;&gt;&lt;/div&gt;&lt;figcaption&gt;Figure 3. Reconstruction: add on the left, subtract on the right.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Next you weight the coefficients by their level in the tree. This is don't to normalize the coefficients.  There are several weighting mechanisms that are popular. Each of them is valid for a different uses. I prefer normalization by multiplying each value by 1/sqrt(2^j) where j is the coefficient's level in the tree.&lt;/p&gt;
&lt;p&gt;Your data now to consists of:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot; aria-label=&quot;text code&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;The scaling value                     { 6 }
The wavelet coefficients              { 1, 5, -3}
The weighted wavelet coefficients     { 1, 5/sqrt(2), -3/sqrt(2) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, no compression has resulted from this process. The entire transformation merely converted four values into four other values and some weighted values which are derived from them.&lt;/p&gt;
&lt;h2 id=&quot;applying-haar&quot;&gt;Applying Haar&lt;/h2&gt;
&lt;p&gt;The next step is to figure out how to apply this to image compression. An image is a two dimensional grid of samples, not a one dimensional set as mentioned above.&lt;/p&gt;
&lt;p&gt;There are two common approaches:&lt;/p&gt;
&lt;p&gt;The standard decomposition of the image would perform the Haar transform on each row and then goes through column by column and transforms each in turn. This unfortunately is not very useful for reconstructing mipmaps, since in order to extract a 2x2 mipmap, I would need to reconstruct the entire image, and then anti-alias my way back down to 2x2. If I were to do this, there would be no advantage in reconstructing the lower mipmaps.&lt;/p&gt;
&lt;p&gt;The nonstandard decomposition transforms one level down each row, and then transforms one level down each column, and repeats until you are left with the scaling function. Thus intuitively, you can extract a 2x2 mipmap from the 1x1 mipmap (aka your scaling coefficient) and the set of coefficients for level 0 (one row coefficient and two column coefficients) and then extract the 4x4 mipmap from the 2x2 using the mipmap and the coefficients for level 1 ( 2 row coefficients, 4 column coefficients), etc. This allows you to reconstruct the image incrementally as you get closer to the surface in the game. Since you manage to avoid any sudden requirements of massive amounts of data, you can avoid stutter.   If you are forced to wait on a higher mipmap in one frame of animation because you didn’t have the processing time to decompress it then you can use the lower mipmap level as a stand in for it until you can. In practice I have found it to be better to maintain a constant 25 frame per second refresh rate rather than dip at times down to 5 because I didn’t have a texture ready.&lt;/p&gt;
&lt;p&gt;I chose to work with the nonstandard decomposition of my texture. This is all well and good, but again so far all we have managed to do is swap one set of numbers for another. No compression has occurred, unless you count the fact that we do not have to store the extra memory for the mipmap levels since they can be derived as we reconstruct the image from the coefficient set.&lt;/p&gt;
&lt;p&gt;The next step is to compress the coefficient set. One advantage that wavelets have is that a small change to the coefficient set creates a similarly small change in the restored sample set, and it nicely distributes such error around the image, thus avoiding visible discontinuities as a result of this error.&lt;/p&gt;
&lt;p&gt;Once you weight them properly by their level in the tree you can eliminate terms that do not contribute much to the overall image by repeatedly throwing away the smallest weighted coefficient (replacing it with 0) until you reach either a stated number of coefficients to remove or a maximum weight to remove. (This heuristic has proved very useful in the past since some images are inherently more forgiving of compression than others. This has made me reluctantly turn the compression stage into an interactive process, but as a consequence it also provides greater artistic control.&lt;/p&gt;
&lt;p&gt;Replacing the coefficients with 0 provides a nice systematic way to provide a bounded maximum error. Unfortunately, it also turned out not to provide a very compressible dataset. Quantizing the remaining coefficients was required. Following the 0 replacement step, I run the set of coefficients through a neural network which performs quantization of the remaining coefficients by using their weighted form. Notice rather than counting each coefficient equally I weight my selection based on the weight of the wavelet coefficient. Yet, when storing to disk I store using the unweighted form. In practice I have found a higher redundancy in value rather than exact weight, and in my case storing the quantized value unweighted provided a better compression ratio.  Running through a neural network for quantizing to a 'palette' of coefficients may seem like overkill, but I had already written the routines to convert to a paletted texture from the 32 bit original representation.   Then I send the smaller set of quantized coefficients and occurrence counters through a Huffman tree generator then I pass the data through a Huffman compressor. Since all of this is a preprocess, the processing time is more or less irrelevant, except that it makes modifications to the game engine more tedious and less fluid. I was able to obtain slightly better compression by skipping the quantization stage and feeding the coefficients directly into a QM arithmetic coder, but the decompression speed suffered greatly and in my eyes it wasn't worth taking 6 times longer to decompress and having to deal with patents held by IBM for a 3% improvement in compression.&lt;/p&gt;
&lt;p&gt;On the down side, compressed textures dramatically increased the complexity of my surface caching algorithm, which makes widespread changes to the game engine itself appreciably more difficult. I also spent a lot more time that I would have liked working on the compression pipeline itself. In retrospect I probably would have been better off using zlib or another library that has been extensively tested and has a nice user interface for the final compression stage.&lt;/p&gt;
&lt;p&gt;The only real problem occurs in high contrast textures. Fortunately, these are usually religiously avoided in polygonal engines because the same general compression artifacts that occur with wavelets are visible when doing mipmapping on the texture. These artifacts can be avoided by anisotropic texture sampling and other techniques, but at the time of this writing, these are not fast enough for realtime graphics and as such are not really relevant. Compression also results in a noticeable increase in the blockiness of the texture proportional to how high you set the error threshold. This blockiness could be ameliorated at the expense of adding a bilinear filtering step, but this would increase problems with high contrast textures.  Bilinear filtering also isn’t really necessary when passing the texture to a high end 3d accelerator card which can do bilinear filtering automatically. As a rule of thumb, textures noticed no artifacts up to 8:1 compression and started to become unusable as I approached 35:1 compression. The usability of the levels in between depended largely on the level of contrast over the majority of the texture. The compressor nicely handled textures which mixed high and low contrast areas. The high contrast areas retained sufficient definition because hard color changes get assigned relatively high weights whereas the low contrast areas simply muted further. The effect of this is to make signs on the wall, technical gadgetry, etc, stand out against a background with a lower frequency of change.&lt;/p&gt;
&lt;p&gt;There is a lot of research being done in the field of wavelets. The Haar basis is really not a very good wavelet basis at all. It is ugly due to the discontinuity of being effectively a hierarchy of pulses and its main advantages are that it is the fastest to extract from an image, to extract an image from, and in the fact that it is fairly intuitive unlike many more advanced wavelets.&lt;/p&gt;
&lt;p&gt;In the course of my work on the game engine I explored several other ways to make wavelets work for me. There exist several basis functions for compressing very high polygon count surfaces. Unfortunately in practice the time it takes to walk the hierarchy and manage a reasonable level of surface data caching outweighs the storage requirements of just precalculating the best tessellation for a given distance and using it in the cases that applied to me. Eventually something of this nature will be required, but at the moment the memory is more plentiful than processing power. Wavelets turned out to be a bit of a let down on this front.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;E. Stollnitz, T. Derose, D. Salesin. &quot;Wavelets for Computer Graphics&quot;, ISBN 1-55860-375-1 Morgan Kaufmann Publishers Inc. San Francisco, CA 1996&lt;/p&gt;
&lt;p&gt;W. Pennebaker, J. Mitchell. &quot;JPEG: Still Image Data Compression Standard&quot;, ISBN 0-442-01272-1 Van Nostrand Reinhold Inc. New York, NY 1993&lt;/p&gt;
&lt;p&gt;D. Morgan. &quot;Numerical Methods for DSP in C&quot;, ISBN 0-471-12232-2 Jon Wiley &amp;amp; Sons Inc. Canada 1997&lt;/p&gt;
&lt;p&gt;B. Hubbard. &quot;The World According to Wavelets&quot;, ISBN 1-56881-047-4 AK Peters Ltd. Welleskey, MA 1996&lt;/p&gt;
&lt;p&gt;Foley, van Dam, Feiner, Hughes, &quot;Computer Graphics: Principles and Practice, 2nd Ed. in C&quot; ISBN 0-201-84840-6 Addison-Wesley Publishing Co. Reading, MA 1996&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://comonad.com/reader/1995/wavelets-in-3d-graphics/&quot;&gt;Read on The Comonad.Reader&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>