Help
RSS
API
Feed
Maltego
Contact
Domain > blog.higher-order.com
×
Welcome!
Right click nodes and scroll the mouse to navigate the graph.
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2013-11-12
199.27.73.133
(
ClassC
)
2013-11-12
199.27.74.133
(
ClassC
)
2013-12-20
199.27.76.133
(
ClassC
)
2015-03-30
199.27.78.133
(
ClassC
)
2016-07-04
151.101.48.133
(
ClassC
)
2024-10-21
185.199.108.153
(
ClassC
)
Port 80
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 234353Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Thu, 20 Sep 2018 02:42:15 GMTAccess-Control-Allow-Origin: *ETag: 5ba30907-39371expires: Mon, 21 Oct 2024 14:09:52 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: C25C:10EB:700D21:733423:67165E57Accept-Ranges: bytesAge: 0Date: Mon, 21 Oct 2024 13:59:52 GMTVia: 1.1 varnishX-Served-By: cache-bfi-krnt7300048-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1729519192.010126,VS0,VE110Vary: Accept-EncodingX-Fastly-Request-ID: 3a6090db2c863f8dd1b920a230b11cd9827580c6 !DOCTYPE html>!--if IEMobile 7 >html classno-js iem7>!endif-->!--if lt IE 9>html classno-js lte-ie8>!endif-->!--if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)>!-->html classno-js langen>!--!endif-->head> meta charsetutf-8> title>Higher Order/title> meta nameauthor contentRúnar Bjarnason> meta namedescription contentI want to talk about a comonad that came up at work the other day. Actually, two of them, as the data structure in question is a comonad in at least …> !-- http://t.co/dKP3o1e --> meta nameHandheldFriendly contentTrue> meta nameMobileOptimized content320> meta nameviewport contentwidthdevice-width, initial-scale1> link relcanonical hrefhttp://runarorama.github.com/> link href/favicon.png relicon> link href/stylesheets/screen.css mediascreen, projection relstylesheet typetext/css> link href/atom.xml relalternate titleHigher Order typeapplication/atom+xml> script src/javascripts/modernizr-2.0.js>/script> script src//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js>/script> script>!window.jQuery && document.write(unescape(%3Cscript src/javascripts/libs/jquery.min.js%3E%3C/script%3E))/script> script src/javascripts/octopress.js typetext/javascript>/script> !--Fonts from Googles Web font directory at http://google.com/webfonts -->link hrefhttp://fonts.googleapis.com/css?familyPT+Serif:regular,italic,bold,bolditalic relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyPT+Sans:regular,italic,bold,bolditalic relstylesheet typetext/css>script typetext/javascript src//use.typekit.net/fbs7fzv.js>/script>script typetext/javascript>try{Typekit.load();}catch(e){}/script> script typetext/javascript> var _gaq _gaq || ; _gaq.push(_setAccount, UA-34544663-1); _gaq.push(_trackPageview); (function() { var ga document.createElement(script); ga.type text/javascript; ga.async true; ga.src (https: document.location.protocol ? https://ssl : http://www) + .google-analytics.com/ga.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s); })(); /script> link href/stylesheets/datatable.css mediascreen, projection relstylesheet typetext/css />/head>body > header rolebanner>hgroup> h1>a href/>Higher Order/a>/h1> h2>Philosophy and functional programming./h2> /hgroup>/header> nav rolenavigation>ul classsubscription data-subscriptionrss> li>a href/atom.xml relsubscribe-rss titlesubscribe via RSS>RSS/a>/li> /ul> form actionhttp://google.com/search methodget> fieldset rolesearch> input typehidden namesitesearch valuerunarorama.github.com> input classsearch typetext nameq results0 placeholderSearch/> /fieldset>/form> ul classmain-navigation> li>a href/>Blog/a>/li> li>a href/blog/archives>Archives/a>/li> li>a href/about>About/a>/li>/ul>/nav> div idmain> div idcontent> div classblog-index> article> header> h1 classentry-title>a href/blog/2016/04/02/a-comonad-of-graph-decompositions/>A Comonad of Graph Decompositions/a>/h1> p classmeta> time classentry-date datetime2016-04-02T13:02:54-04:00>span classdate>span classdate-month>Apr/span> span classdate-day>2/span>span classdate-suffix>nd/span>, span classdate-year>2016/span>/span> span classtime>1:02 pm/span>/time> /p> /header> div classentry-content>p>I want to talk about a comonad that came up at a hrefhttp://innovation.verizon.com/>work/a> the other day. Actually, two of them, as the data structure in question is a comonad in at least two ways, and the issue that came up is related to the difference between those two comonads./p>p>This post is sort of a continuation of the a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>Comonad Tutorial/a>, and we can call this “part 3”. I’m going to assume the reader has a basic familiarity with comonads./p>h2>Inductive Graphs/h2>p>At a hrefhttp://innovation.verizon.com/>work/a>, we develop and use a Scala library called a hrefhttp://github.com/oncue/quiver>Quiver/a> for working with a hrefhttps://en.wikipedia.org/wiki/Graph_(discrete_mathematics>graphs/a>). In this library, a graph is a recursively defined immutable data structure. A graph, with node IDs of type code>V/code>, node labels code>N/code>, and edge labels code>E/code>, is constructed in one of two ways. It can be empty:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>empty/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Or it can be of the form code>c & g/code>, where code>c/code> is the em>context/em> of one node of the graph and code>g/code> is the rest of the graph with that node removed:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>/span>span classline> span classn>inEdges/span>span classk>:/span> span classkt>Vector/span>span classo>(/span>span classkt>E/span>,span classkt>V/span>span classo>),/span>/span>span classline> span classn>vertex/span>span classk>:/span> span classkt>V/span>span classo>,/span>/span>span classline> span classn>label/span>span classk>:/span> span classkt>N/span>span classo>,/span>/span>span classline> span classn>outEdges/span>span classk>:/span> span classkt>Vector/span>span classo>(/span>span classkt>E/span>,span classkt>V/span>span classo>)/span>/span>span classline>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classo>&(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span> span classk>/span> span classo>???/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>By the same token, we can decompose a graph on a particular node:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>span classline>span classn>v/span>span classk>:/span> span classkt>V/span>/span>span classline>/span>span classline>span classn>g/span> span classn>decomp/span> span classn>v/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Where a code>GDecomp/code> is a code>Context/code> for the node code>v/code> (if it exists in the graph) together with the rest of the graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>ctx/span>span classk>:/span> span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>,/span> span classn>rest/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Recursive decomposition/h2>p>Let’s say we start with a graph code>g/code>, like this:/p>p>img src/images/quiver/Quiver1.png width300 altExample graph />/p>p>I’m using an em>undirected/em> graph here for simplification. An undirected graph is one in which the edges don’t have a direction. In Quiver, this is represented as a graph where the “in” edges of each node are the same as its “out” edges./p>p>If we decompose on the node code>a/code>, we get a view of the graph from the perspective of code>a/code>. That is, we’ll have a code>Context/code> letting us look at the label, vertex ID, and edges to and from code>a/code>, and we’ll also have the remainder of the graph, with the node code>a/code> “broken off”:/p>p>img src/images/quiver/decompa.png width400 altGDecomp on a />/p>p>Quiver can arbitrarily choose a node for us, so we can look at the context of some “first” node:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>span classline>/span>span classline>span classn>g/span>span classo>./span>span classn>decompAny/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>We can keep decomposing the remainder recursively, to perform an arbitrary calculation over the entire graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>f/span>span classk>:/span> span classo>(/span>span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>,/span> span classn>B/span>span classo>)/span> span classk>>/span> span classn>B/span>/span>span classline>span classn>b/span>span classk>:/span> span classkt>B/span>/span>span classline>/span>span classline>span classo>(/span>span classn>g/span> span classn>fold/span> span classn>b/span>span classo>)(/span>span classn>f/span>span classo>)/span>span classk>:/span> span classkt>B/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The implementation of code>fold/code> will be something like:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classo>./span>span classn>decompAny/span> span classn>map/span> span classo>{/span>/span>span classline> span classk>case/span> span classnc>GDecomp/span>span classo>(/span>span classn>ctx/span>span classo>,/span> span classn>rest/span>span classo>)/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>ctx/span>span classo>,/span> span classn>rest/span>span classo>./span>span classn>fold/span>span classo>(/span>span classn>b/span>span classo>)(/span>span classn>f/span>span classo>))/span>/span>span classline>span classo>}/span> span classn>getOrElse/span> span classn>b/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>For instance, if we wanted to count the edges in the graph code>g/code>, we could do:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classo>(/span>span classn>g/span> span classn>fold/span> span classmi>0/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classn>b/span>span classo>)/span> span classk>>/span> span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>b/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The recursive decomposition will guarantee that our function doesn’t see any given edge more than once. For the graph code>g/code> above, code>(g fold b)(f)/code> would look something like this:/p>p>img src/images/quiver/fold.png altGraph fold />/p>h2>Graph Rotations/h2>p>Let’s now say that we wanted to find the maximum a hrefhttps://en.wikipedia.org/wiki/Degree_(graph_theory>degree/a> of a graph. That is, find the highest number of edges to or from any node./p>p>A first stab might be:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classo>(/span>span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span>span classo>)/span> span classn>max/span> span classn>z/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But that would get the incorrect result. In our graph code>g/code> above, the nodes code>b/code>, code>d/code>, and code>f/code> have a degree of 3, but this fold would find the highest degree to be 2. The reason is that once our function gets to look at code>b/code>, its edge to code>a/code> has already been removed, and once it sees code>f/code>, it has no edges left to look at./p>p>This was the issue that came up at work. This behaviour of code>fold/code> is both correct and useful, but it can be surprising. What we might expect is that instead of receiving successive decompositions, our function sees “all rotations” of the graph through the code>decomp/code> operator:/p>p>img src/images/quiver/rotations.png altAll rotations />/p>p>That is, we often want to consider each node in the context of the entire graph we started with. In order to express that with code>fold/code>, we have to decompose the original graph at each step:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decompose/span>span classo>(/span>span classn>c/span>span classo>./span>span classn>vertex/span>span classo>)./span>span classn>map/span> span classo>{/span>/span>span classline> span classk>case/span> span classnc>GDecomp/span>span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classk>_/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span>/span>span classline> span classo>}./span>span classn>getOrElse/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classn>max/span> span classn>z/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But what if we could have a combinator that em>labels each node with its context/em>?/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>contextGraph/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visually, that looks something like this:/p>p>img src/images/quiver/duplicate.png altAll contexts />/p>p>If we now fold over code>contextGraph(g)/code> rather than code>g/code>, we get to see the whole graph from the perspective of each node in turn. We can then write the code>maxDegree/code> function like this:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>contextGraph/span>span classo>(/span>span classn>g/span>span classo>)./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>z/span> span classn>max/span> span classo>(/span>span classn>c/span>span classo>./span>span classn>label/span>span classo>./span>span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>c/span>span classo>./span>span classn>label/span>span classo>./span>span classn>outs/span>span classo>./span>span classn>size/span>span classo>)/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Two different comonads/h2>p>This all sounds suspiciously like a comonad! Of course, code>Graph/code> itself is not a comonad, but code>GDecomp/code> definitely is. The code>counit/code> just gets the label of the node that’s been code>decomp/code>ed out:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>gdecompComonad/span>span classo>/span>span classkt>V/span>,span classkt>E/span>span classo>/span> span classk>/span> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>α/span>,span classkt>E/span>span classo>/span> span classo>{/span>/span>span classline>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>label/span>/span>span classline>/span>span classline> span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classo>???/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>cobind/code> can be implemented in one of two ways. There’s the “successive decompositions” version:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classnc>GDecomp/span>span classo>(/span>span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>g/span>span classo>)),/span>/span>span classline> span classn>g/span>span classo>./span>span classn>rest/span>span classo>./span>span classn>decompAny/span>span classo>./span>span classn>map/span> span classo>{/span>/span>span classline> span classk>val/span> span classnc>GDecomp/span>span classo>(/span>span classn>c/span>span classo>,/span> span classn>r/span>span classo>)/span> span classk>/span> span classn>cobind/span>span classo>(/span>span classk>_/span>span classo>)(/span>span classn>f/span>span classo>)/span>/span>span classline> span classn>c/span> span classo>&/span> span classn>r/span>/span>span classline> span classo>}/span> span classn>getOrElse/span> span classn>empty/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visually, it looks like this:/p>p>img src/images/quiver/extend.png altExtend over successive decompositions />/p>p>It em>exposes the substructure/em> of the graph by storing it in the labels of the nodes. It’s very much like the familiar code>NonEmptyList/code> comonad, which replaces each element in the list with the whole sublist from that element on./p>p>So this is the comonad of em>recursive folds over a graph/em>. Really its action is the same as as just code>fold/code>. It takes a computation on one decomposition of the graph, and extends it to all sub-decompositions./p>p>But there’s another, comonad that’s much more useful em>as a comonad/em>. That’s the comonad that works like code>contextGraph/code> from before, except instead of copying the context of a node into its label, we copy the whole decomposition; both the context and the remainder of the graph./p>p>That one looks visually more like this:/p>p>img src/images/quiver/redecorate.png altExtend over all rotations />/p>p>Its code>cobind/code> takes a computation focused on one node of the graph (that is, on a code>GDecomp/code>), repeats that for every other decomposition of the original graph in turn, and stores the results in the respective node labels:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classk>val/span> span classn>orig/span> span classk>/span> span classn>g/span>span classo>./span>span classn>ctx/span> span classo>&/span> span classn>g/span>span classo>./span>span classn>rest/span>/span>span classline> span classnc>GDecomp/span>span classo>(/span>span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>g/span>span classo>)),/span>/span>span classline> span classn>rest/span>span classo>./span>span classn>fold/span>span classo>(/span>span classn>empty/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>acc/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>c/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>orig/span>span classo>./span>span classn>decomp/span>span classo>(/span>span classn>c/span>span classo>./span>span classn>vertex/span>span classo>)./span>span classn>get/span>span classo>))/span> span classo>&/span> span classn>acc/span>/span>span classline> span classo>})/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This is useful for algorithms where we want to label every node with some information computed from its neighborhood. For example, some clustering algorithms start by assigning each node its own cluster, then repeatedly joining nodes to the most popular cluster in their immediate neighborhood, until a fixed point is reached./p>p>As a simpler example, we could take the average value for the labels of neighboring nodes, to apply something like a low-pass filter to the whole graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>lopass/span>span classo>/span>span classkt>V/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Int/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Int/span>,span classkt>E/span>span classo>/span> span classk>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decompAny/span>span classo>./span>span classn>map/span> span classo>{/span> span classn>d/span> span classk>>/span> span classn>cobind/span>span classo>(/span>span classn>d/span>span classo>)/span> span classo>{/span> span classn>x/span> span classk>>/span>/span>span classline> span classk>val/span> span classn>neighbors/span> span classk>/span> span classo>(/span>span classn>x/span>span classo>./span>span classn>inEdges/span> span classo>++/span> span classn>x/span>span classo>./span>span classn>outEdges/span>span classo>)./span>span classn>map/span> span classo>{/span> span classn>n/span> span classk>>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decomp/span>span classo>(/span>span classn>n/span>span classo>)./span>span classn>get/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>label/span>/span>span classline> span classo>}/span>/span>span classline> span classo>(/span>span classn>neighbors/span>span classo>./span>span classn>sum/span> span classo>+/span> span classn>x/span>span classo>./span>span classn>label/span>span classo>)/span> span classo>//span> span classo>(/span>span classn>neighbors/span>span classo>./span>span classn>length/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classo>}}/span> span classn>getOrElse/span> span classn>g/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The difference between these two comonad instances is essentially the same as the difference between a hrefhttps://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/NonEmptyList.scala>code>NonEmptyList/code>/a> and the nonempty list a hrefhttps://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Zipper.scala>code>Zipper/code>/a>./p>p>It’s this latter “decomp zipper” comonad that I decided to ultimately include as the code>Comonad/code> instance for code>quiver.GDecomp/code>./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/10/12/freedom-and-forgetfulness/>Freedom and Forgetfulness/a>/h1> p classmeta> time classentry-date datetime2015-10-12T23:13:54-04:00>span classdate>span classdate-month>Oct/span> span classdate-day>12/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:13 pm/span>/time> /p> /header> div classentry-content>p>I’ve been having fun exploring adjunctions lately and thinking about how we can take a monad apart and compose it the other way to get a comonad, and vice versa. Often I’ll find that a comonad counterpart of a given monad gives an interesting perspective on that monad, and ditto for a monad cousin to a given comonad./p>h2>The monad for monoids/h2>p>Let’s take an example. There is a category of monoids em>Mon/em> with monoids as objects and monoid homomorphisms as arrows between them. Then there is a functor from em>Set/em> to em>Mon/em> that takes any ordinary type code>A/code> to the em>free monoid/em> generated by code>A/code>. This is just the code>ListA/code> type together with concatenation as the multiplication and the empty list as the identity element./p>p>This free functor has a right adjoint that takes any monoid code>M/code> in em>Mon/em> to its em>underlying set/em> code>M/code>. That is, this right adjoint “forgets” that code>M/code> is a monoid, leaving us with just an ordinary type./p>p>If we compose these two functors, we get a monad. If we start with a type code>A/code>, get its free monoid (the code>ListA/code> monoid), and then go from there to the underlying type of the free monoid, we end up with the type code>ListA/code>. The code>unit/code> of our adjunction is then a function from any given type code>A/code> to the type code>ListA/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>List/span>span classo>(/span>span classn>a/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h3>Structure ⊣ Interpretation/h3>p>But then what is the code>counit/code>? Remember that for any adjunction, we can compose the functors one way to get a monad, and compose them the other way to get a comonad./p>p>In that case we have to start with a monoid code>M/code>, then “forget”, giving us the plain type code>M/code>. Then we take the free monoid of that to end up with the code>ListM/code> monoid./p>p>But notice that we are now in the monoid category. In that category, code>List/code> is a comonad. And since we’re in the category of monoids, the code>counit/code> has to be a em>monoid homomorphism/em>. It goes from the free monoid code>ListA/code> to the monoid code>A/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A:Monoid/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>foldRight/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>A/span>span classo>./span>span classn>zero/span>span classo>)(/span>span classnc>Monoid/span>span classo>/span>span classkt>A/span>span classo>./span>span classn>append/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>If we apply the code>counit/code> for this comonad to the free monoid, we get the code>join/code> for our monad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classn>counit/span>span classo>(/span>span classn>as/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And to get the code>duplicate/code> or code>extend/code> operation in the comonad, we just turn the crank on the adjunction:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classk>_/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>duplicate/code> just puts each element into its own sublist. With regard to code>extend/code>, this just means that given any catamorphism on code>List/code>, we can turn that into a homomorphism on free monoids./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>x/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classn>x/span>span classo>)))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>All the interesting parts of code>List/code> are the parts that make it a monoid, and our comonad here is already in a category full of monoids. Therefore the coKleisli composition in this comonad is kind of uninteresting. All it’s saying is that if we can fold a code>ListA/code> to a code>B/code>, and a code>ListB/code> to a code>C/code>, then we can fold a code>ListA/code> to a code>C/code>, by considering each element as a singleton list./p>h2>Forget ⊣ Cofree/h2>p>Let’s now consider another category, call it em>End(Set)/em>, which is the em>category of endofunctors/em> in em>Set/em>./p>p>The arrows in this category are natural transformations:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>~>/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>apply/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>There’s another category, em>Com/em>, which is the em>category of comonads/em> on em>Set/em>. The arrows here are em>comonad homomorphisms/em>. A comonad homomorphism from code>F/code> to code>G/code> is a natural transformation code>f: F ~> G/code> satisfying the homomorphism law:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>f/span>span classo>(/span>span classn>x/span>span classo>)./span>span classn>duplicate/span> span classo>/span> span classn>f/span>span classo>(/span>span classn>x/span>span classo>./span>span classn>duplicate/span>span classo>)/span> span classn>map/span> span classn>f/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>There is a forgetful functor code>Forget: Com -> End(Set)/code> that takes a comonad to its underlying endofunctor (forgetting that it’s a comonad). And this functor has a em>right/em> adjoint code>Cofree: End(Set) -> Com/code> which generates a cofree comonad on a given endofunctor code>F/code>. This is the following data type:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cofree/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that not only is the endofunctor code>CofreeF,?/code> a comonad (in em>Set/em>) for any functor code>F/code>, but the higher-order type constructor code>Cofree/code> is itself is a comonad in the endofunctor category. It’s this latter comonad that is induced by the code>Forget ⊣ Cofree/code> adjunction. That is, we start at an endofunctor code>F/code>, then go to comonads via code>CofreeF,?/code>, then back to endofunctors via code>Forget/code>./p>p>The code>unit/code> for this adjunction is then a comonad homomorphism. Remember, this is the code>unit/code> for a monad in the category em>Com/em> of comonads:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Comonad/span>,span classkt>A/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cofree/span>span classo>(/span>span classn>x/span>span classo>./span>span classn>counit/span>span classo>,/span> span classn>x/span>span classo>./span>span classn>extend/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classk>_/span>span classo>)))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This will start with a value of type code>FA/code> in the comonad code>F/code>, and then em>unfold/em> an code>F/code>-branching stream from it. Note that the first level of this will have the same structure as code>x/code>./p>p>If we take code>unit/code> across to the em>End(Set)/em> category, we get the code>duplicate/code> for our comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>?/span>span classo>/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>unit/span>span classo>(/span>span classn>c/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that this is em>not/em> the code>duplicate/code> for the code>CofreeF,?/code> comonad. It’s the duplicate for code>Cofree/code> itself which is a comonad in an endofunctor category./p>p>Turning the crank on the adjunction, the code>counit/code> for this comonad now has to be the inverse of our code>unit/code>. It takes the heads of all the branches of the given code>F/code>-branching stream./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Functor/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>c/span>span classo>./span>span classn>tail/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>head/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Sending that over to the comonad category, we get the code>join/code> for our monad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Comonad/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>?/span>span classo>/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>counit/span>span classo>(/span>span classn>c/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>/div> /article> article> header> h1 classentry-title>a href/blog/2015/10/04/scala-comonad-tutorial-part-2/>Scala Comonad Tutorial, Part 2/a>/h1> p classmeta> time classentry-date datetime2015-10-04T17:36:31-04:00>span classdate>span classdate-month>Oct/span> span classdate-day>4/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>5:36 pm/span>/time> /p> /header> div classentry-content>p>In the a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>previous post/a>, we looked at the Reader/Writer monads and comonads, and discussed in general what comonads are and how they relate to monads. This time around, we’re going to look at some more comonads, delve briefly into adjunctions, and try to get some further insight into what it all means./p>h2>Nonempty structures/h2>p>Since a comonad has to have a code>counit/code>, it must be “pointed” or nonempty in some sense. That is, given a value of type code>WA/code> for some comonad code>W/code>, we must be able to get a value of type code>A/code> out./p>p>The identity comonad is a simple example of this. We can always get a value of type code>A/code> out of code>IdA/code>. A slightly more interesting example is that of non-empty lists:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>NEL/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>So a nonempty list is a value of type code>A/code> together with either another list or code>None/code> to mark that the list has terminated. Unlike the traditional code>List/code> data structure, we can always safely get the code>head/code>./p>p>But what is the comonadic code>duplicate/code> operation here? That should allow us to go from code>NELA/code> to code>NELNELA/code> in such a way that the comonad laws hold. For nonempty lists, an implementation that satisfies those laws turns out to be:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>NEL/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classo>.../span>/span>span classline> span classk>def/span> span classn>tails/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>NEL/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>tail/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>tails/span>span classo>))/span>/span>span classline> span classo>.../span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>tails/code> operation returns a list of all the suffixes of the given list. This list of lists is always nonempty, because the first suffix is the list itself. For example, if we have the nonempty list code>1,2,3/code> (to use a more succinct notation), the code>tails/code> of that will be code>1,2,3, 2,3, 3/code>/p>p>To get an idea of what this em>means/em> in the context of a comonadic program, think of this in terms of coKleisli composition, or code>extend/code> in the comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>tails/span> span classn>map/span> span classn>f/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>When we code>map/code> over code>tails/code>, the function code>f/code> is going to receive each suffix of the list in turn. We apply code>f/code> to each of those suffixes and collect the results in a (nonempty) list. So code>1,2,3.extend(f)/code> will be code>f(1,2,3), f(2,3), f(3)/code>./p>p>The name code>extend/code> refers to the fact that it takes a “local” computation (here a computation that operates on a list) and extends that to a “global” computation (here over all suffixes of the list)./p>p>Or consider this class of nonempty trees (often called Rose Trees):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Tree/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>tip/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>sub/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>Tree/span>span classo>/span>span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>A tree of this sort has a value of type code>A/code> at the tip, and a (possibly empty) list of subtrees underneath. One obvious use case is something like a directory structure, where each code>tip/code> is a directory and the corresponding code>sub/code> is its subdirectories./p>p>This is also a comonad. The code>counit/code> is obvious, we just get the code>tip/code>. And here’s a code>duplicate/code> for this structure:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Tree/span>span classo>/span>span classkt>Tree/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Tree/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>sub/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>duplicate/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now, this obviously gives us a tree of trees, but what is the structure of that tree? It will be em>a tree of all the subtrees/em>. The code>tip/code> will be code>this/code> tree, and the code>tip/code> of each proper subtree under it will be the entire subtree at the corresponding point in the original tree./p>p>That is, when we say code>t.duplicate.map(f)/code> (or equivalently code>t extend f/code>), our code>f/code> will receive each subtree of code>t/code> in turn and perform some calculation over that entire subtree. The result of the whole expression code>t extend f/code> will be a tree mirroring the structure of code>t/code>, except each node will contain code>f/code> applied to the corresponding subtree of code>t/code>./p>p>To carry on with our directory example, we can imagine wanting a detailed space usage summary of a directory structure, with the size of the whole tree at the code>tip/code> and the size of each subdirectory underneath as tips of the subtrees, and so on. Then code>d extend size/code> creates the tree of sizes of recursive subdirectories of code>d/code>./p>h2>The cofree comonad/h2>p>You may have noticed that the implementations of code>duplicate/code> for rose trees and code>tails/code> for nonempty lists were basically identical. The only difference is that one is mapping over a code>List/code> and the other is mapping over an code>Option/code>. We can actually abstract that out and get a comonad for any functor code>F/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cofree/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>counit/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>sub/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>(/span>span classk>implicit/span> span classn>F/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>F/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cofree/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>F/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>sub/span>span classo>)(/span>span classk>_/span>span classo>./span>span classn>duplicate/span>span classo>))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>A really common kind of structure is something like the type code>CofreeMapK,?,A/code> of trees where the code>counit/code> is some kind of summary and each key of type code>K/code> in the code>Map/code> of subtrees corresponds to some drilldown for more detail. This kind of thing appears in portfolio management applications, for example./p>p>Compare this structure with the em>free monad/em>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>sealed/span> span classk>trait/span> span classnc>Free/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>/span>/span>span classline>span classnc>case/span> span classk>class/span> span classnc>Return/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classk>extends/span> span classnc>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span>/span>span classline>span classk>case/span> span classk>class/span> span classnc>Suspend/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span> span classk>extends/span> span classnc>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>While the free monad is em>either/em> an code>A/code> or a recursive step suspended in an code>F/code>, the cofree comonad is em>both/em> an code>A/code> em>and/em> a recursive step suspended in an code>F/code>. They really are duals of each other in the sense that the monad is a coproduct and the comonad is a product./p>h2>Comparing comonads to monads (again)/h2>p>Given this difference, we can make some statements about what it means:/p>ul>li>code>FreeF,A/code> is a type of “leafy tree” that branches according to code>F/code>, with values of type code>A/code> at the leaves, while code>CofreeF,A/code> is a type of “node-valued tree” that branches according to code>F/code> with values of type code>A/code> at the nodes./li>li>If code>Exp/code> defines the structure of some expression language, then code>FreeExp,A/code> is the type of abstract syntax trees for that language, with free variables of type code>A/code>, and monadic code>bind/code> literally binds expressions to those variables. Dually, code>CofreeExp,A/code> is the type of em>closed/em> exresspions whose subexpressions are annotated with values of type code>A/code>, and comonadic code>extend/code> em>reannotates/em> the tree. For example, if you have a type inferencer code>infer/code>, then code>e extend infer/code> will annotate each subexpression of code>e/code> with its inferred type./li>/ul>p>This comparison of code>Free/code> and code>Cofree/code> actually says something about monads and comonads in general:/p>ul>li>All monads can model some kind of leafy tree structure, and all comonads can be modeled by some kind of node-valued tree structure./li>li>In a monad code>M/code>, if code>f: A > MB/code>, then code>xs map f/code> allows us to take the values at the leaves (code>a:A/code>) of a monadic structure code>xs/code> and em>substitute/em> an entire structure (code>f(a)/code>) for each value. A subsequent code>join/code> then renormalizes the structure, eliminating the “seams” around our newly added substructures. In a em>comonad/em> code>W/code>, code>xs.duplicate/code> denormalizes, or exposes the substructure of code>xs:WA/code> to yield code>WWA/code>. Then we can map a function code>f: WA > B/code> over that to get a code>B/code> for each part of the substructure and em>redecorate/em> the original structure with those values. (See Uustalu and Vene’s excellent paper a hrefhttp://cs.ioc.ee/~tarmo/papers/sfp01-book.pdf>The Dual of Substitution is Redecoration/a> for more on this connection.)/li>li>A monad defines a class of programs whose subexpressions are incrementally generated from the outputs of previous expressions. A comonad defines a class of programs that incrementally generate output from the substructure of previous expressions./li>li>A monad adds structure by consuming values. A comonad adds values by consuming structure./li>/ul>h2>The relationship between Reader and Coreader/h2>p>If we look at a Kleisli arrow in the code>ReaderR,?/code> comonad, it looks like code>A > ReaderR,B/code>, or expanded out: code>A > R > B/code>. If we uncurry that, we get code>(A, R) > B/code>, and we can go back to the original by currying again. But notice that a value of type code>(A, R) > B/code> is a coKleisli arrow in the code>Coreader/code> comonad! Remember that code>CoreaderR,A/code> is really a pair code>(A, R)/code>./p>p>So the answer to the question of how code>Reader/code> and code>Coreader/code> are related is that there is a one-to-one correspondence between a Kleisli arrow in the code>Reader/code> monad and a coKleisli arrow in the code>Coreader/code> comonad. More precisely, the Kleisli category for code>ReaderR,?/code> is isomorphic to the coKleisli category for code>CoreaderR,?/code>. This isomorphism is witnessed by currying and uncurrying./p>p>In general, if we have an isomorphism between arrows like this, we have what’s called an em>adjunction/em>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Adjunction/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>left/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>B/span>span classo>/span>/span>span classline> span classk>def/span> span classn>right/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>In an code>AdjunctionF,G/code>, we say that code>F/code> is em>left adjoint/em> to code>G/code>, often expressed with the notation code>F ⊣ G/code>./p>p>We can clearly make an code>Adjunction/code> for code>CoreaderR,?/code> and code>ReaderR,?/code> by using code>curry/code> and code>uncurry/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>homSetAdj/span>span classo>/span>span classkt>R/span>span classo>/span> span classk>/span> span classk>new/span> span classnc>Adjunction/span>span classo>(/span>span classkt>?/span>, span classkt>R/span>span classo>)/span>, span classkt>R/span> span classk>>/span> span classkt>?/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>left/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classo>((/span>span classkt>A/span>span classo>,/span> span classkt>R/span>span classo>))/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>R/span> span classk>>/span> span classn>B/span> span classk>/span>/span>span classline> span classnc>Function/span>span classo>./span>span classn>untupled/span>span classo>(/span>span classn>f/span>span classo>)./span>span classn>curried/span>/span>span classline> span classk>def/span> span classn>right/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>R/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classo>((/span>span classkt>A/span>span classo>,/span> span classkt>R/span>span classo>))/span> span classk>>/span> span classn>B/span> span classk>/span>/span>span classline> span classnc>Function/span>span classo>./span>span classn>uncurried/span>span classo>(/span>span classn>f/span>span classo>)./span>span classn>tupled/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The additional code>tupled/code> and code>untupled/code> come from the unfortunate fact that I’ve chosen Scala notation here and Scala differentiates between functions of two arguments and functions of one argument that happens to be a pair./p>p>So a more succinct description of this relationship is that code>Coreader/code> is left adjoint to code>Reader/code>./p>p>Generally the left adjoint functor em>adds/em> structure, or is some kind of “producer”, while the right adjoint functor em>removes/em> (or “forgets”) structure, or is some kind of “consumer”./p>h2>Composing adjoint functors/h2>p>An interesting thing about adjunctions is that if you have an adjoint pair of functors code>F ⊣ G/code>, then code>FG?/code> always forms a comonad, and code>GF?/code> always forms a monad, in a completely canonical and amazing way:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>monad/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>(/span>span classn>A/span>span classk>:/span> span classkt>Adjunction/span>span classo>/span>span classkt>F/span>,span classkt>G/span>span classo>)(/span>span classk>implicit/span> span classn>G/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>G/span>span classo>)/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Monad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>α/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classo>>/span> span classn>A/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>A/span>span classo>./span>span classn>left/span>span classo>(/span>span classn>identity/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>a/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>bind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>B/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>G/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>a/span>span classo>)(/span>span classn>A/span>span classo>./span>span classn>right/span>span classo>(/span>span classn>f/span>span classo>))/span>/span>span classline> span classo>}/span>/span>span classline>/span>span classline>span classk>def/span> span classn>comonad/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>(/span>span classn>A/span>span classk>:/span> span classkt>Adjunction/span>span classo>/span>span classkt>F/span>,span classkt>G/span>span classo>)(/span>span classk>implicit/span> span classn>F/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>F/span>span classo>)/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>α/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>A/span>span classo>./span>span classn>right/span>span classo>(/span>span classn>identity/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>a/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>F/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>a/span>span classo>)(/span>span classn>A/span>span classo>./span>span classn>left/span>span classo>(/span>span classn>f/span>span classo>))/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that this says something about monads and comonads. Since the left adjoint code>F/code> is a producer and the right adjoint code>G/code> is a consumer, a monad always consumes and then produces, while a comonad always produces and then consumes./p>p>Now, if we compose code>Reader/code> and code>Coreader/code>, which monad do we get?/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>scala/span>span classo>>/span> span classk>def/span> span classn>M/span>span classo>/span>span classkt>S/span>span classo>/span> span classk>/span> span classn>monad/span>span classo>(/span>span classn>homSetAdj/span>span classo>/span>span classkt>S/span>span classo>)/span>/span>span classline>span classn>M/span>span classk>:/span> span classerr>/span>span classkt>S/span>span classerr>/span>span classo>>/span> span classn>scalaz/span>span classo>./span>span classnc>Monad/span>span classo>/span>span classkt>α/span>span classo>/span>span classkt>S/span> span classk>>/span> span classo>(/span>span classkt>α/span>, span classkt>S/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>That’s the code>StateS,?/code> monad!/p>p>Now if we compose it the other way, we should get a comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>scala/span>span classo>>/span> span classk>def/span> span classn>W/span>span classo>/span>span classkt>S/span>span classo>/span> span classk>/span> span classn>comonad/span>span classo>(/span>span classn>homSetAdj/span>span classo>/span>span classkt>S/span>span classo>)/span>/span>span classline>span classn>W/span>span classk>:/span> span classerr>/span>span classkt>S/span>span classerr>/span>span classo>>/span> span classn>scalaz/span>span classo>./span>span classnc>Comonad/span>span classo>/span>span classkt>α/span>span classo>(/span>span classkt>S/span> span classk>>/span> span classkt>α/span>, span classkt>S/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>What is that? It’s the code>StoreS,?/code> comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>peek/span>span classk>:/span> span classkt>S/span> span classo>>/span> span classn>A/span>span classo>,/span> span classn>cursor/span>span classk>:/span> span classkt>S/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>extract/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>peek/span>span classo>(/span>span classn>cursor/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>, span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Store/span>span classo>(/span>span classn>s/span> span classk>>/span> span classn>f/span>span classo>(/span>span classnc>Store/span>span classo>(/span>span classn>peek/span>span classo>,/span> span classn>s/span>span classo>)),/span> span classn>cursor/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>, span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>extend/span>span classo>(/span>span classn>identity/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>extend/span>span classo>(/span>span classn>s/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>s/span>span classo>./span>span classn>extract/span>span classo>))/span>/span>span classline>/span>span classline> span classk>def/span> span classn>seek/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>S/span>span classo>)/span> span classk>/span> span classn>duplicate/span>span classo>./span>span classn>peek/span>span classo>(/span>span classn>s/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This models a “store” of values of type code>A/code> indexed by the type code>S/code>. We have the ability to directly access the code>A/code> value under a given code>S/code> using code>peek/code>, and there is a distinguished code>cursor/code> or current position. The comonadic code>extract/code> just reads the value under the code>cursor/code>, and code>duplicate/code> gives us a whole store full of stores such that if we code>peek/code> at any one of them, we get a code>Store/code> whose code>cursor/code> is set to the given code>s/code>. We’re defining a code>seek(s)/code> operation that moves the code>cursor/code> to a given position code>s/code> by taking advantage of code>duplicate/code>./p>p>A use case for this kind of structure might be something like image processing or cellular automata, where code>S/code> might be coordinates into some kind of space (like a two-dimensional image). Then code>extend/code> takes a local computation at the code>cursor/code> and extends it to every point in the space. For example, if we have an operation code>average/code> that peeks at the code>cursor/code>’s immediate neighbors and averages them, then we can apply a low-pass filter to the whole image with code>image.extend(average)/code>./p>p>The type code>A > StoreS,B/code> is also one possible representation of a a hrefhttp://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.package%24%24Lens%24>Lens/a>. I might talk about lenses and a hrefhttp://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.Zipper>zippers/a> in a future post./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/09/30/the-adjunction-that-induces-the-reader-monad/>An Adjunction That Induces the Reader Monad/a>/h1> p classmeta> time classentry-date datetime2015-09-30T07:48:13-04:00>span classdate>span classdate-month>Sep/span> span classdate-day>30/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>7:48 am/span>/time> /p> /header> div classentry-content>p>In writing up part 2 of my a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>Scala Comonad Tutorial/a>, and coming up with my talk for a hrefhttp://scala.world>Scala World/a>, I idly pondered this question:/p>blockquote>p>If all monads are given by composing adjoint pairs of functors, what adjoint pair of functors forms the `Reader` monad? And if we compose those functors the other way, which comonad do we get?/p>/blockquote>p>Shachaf Ben-Kiki pointed out on IRC that there are at least two ways of doing this. One is via the a hrefhttps://en.wikipedia.org/wiki/Kleisli_category#Kleisli_adjunction>Kleisli construction/a> and the other is via the a hrefhttp://ncatlab.org/nlab/show/Eilenberg-Moore+category>Eilenberg-Moore construction/a>. Dr Eugenia Cheng has a a hrefhttps://www.youtube.com/playlist?listPL54B49729E5102248>fantastic set of videos explaining these constructions/a>. She talks about how for any monad code>T/code> there is a whole category code>Adj(T)/code> of adjunctions that give rise to code>T/code> (with categories as objects and adjoint pairs of functors as the arrows), and the Kleisli category is the initial object in this category while the Eilenberg-Moore category is the terminal object./p>p>So then, searching around for an answer to what exactly the Eilenberg-Moore category for the code>R > ?/code> monad looks like (I think it’s just values of type code>R/code> and functions between them), I came across a hrefhttp://math.stackexchange.com/questions/1274989/what-is-the-eilenberg-moore-category-of-this-diagonal-like-monad>this Mathematics Stack Exchange question/a>, whose answer more or less directly addresses my original question above. The adjunction is a little more difficult to see than the initial/terminal ones, but it’s somewhat interesting, and what follows is an outline of how I convinced myself that it works./p>h2>The adjoint pair/h2>p>Let’s consider the reader monad code>R > ?/code>, which allows us to read a context of type code>R/code>./p>p>The first category involved is em>Set/em> (or em>Hask/em>, or em>Scala/em>). This is just the familiar category where the objects are types (code>A/code>,code>B/code>,code>C/code>, etc.) and the arrows are functions./p>p>The other category is em>Set/R/em>, which is the a hrefhttp://ncatlab.org/nlab/show/overcategory>slice category/a> of em>Set/em> over the type code>R/code>. This is a category whose objects are functions to code>R/code>. So an object code>x/code> in this category is given by a type code>A/code> together with a function of type code>A > R/code>. An arrow from code>x: A > R/code> to code>y: B > R/code> is given by a function code>f: A > B/code> such that code>y(f(a)) x(a)/code> for all code>a:A/code>./p>p>The left adjoint is code>R*/code>, a functor from em>Set/em> to em>Set/R/em>. This functor sends each type code>A/code> to the function code>(p:(R,A)) > p._1/code>, having type code>(R,A) > R/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>rStar/span>span classo>/span>span classkt>A/span>span classo>/span>span classk>:/span> span classo>(/span>span classkt>R/span>span classo>,/span>span classkt>A/span>span classo>)/span> span classk>>/span> span classn>R/span> span classk>/span> span classk>_/span>span classo>./span>span classn>_1/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The right adjoint is code>Π_R/code>, a functor from em>Set/R/em> to em>Set/em>. This functor sends each object code>q: A > R/code> in em>Set/R/em> to the set of functions code>R > A/code> for which code>q/code> is an inverse. This is actually a dependent type inhabited by functions code>p: R > A/code> which satisfy the identity code>q(p(a)) a/code> for all code>a:A/code>./p>h2>Constructing the monad/h2>p>The monad is not exactly easy to see, but if everything has gone right, we should get the code>R > ?/code> reader monad by composing code>Π_R/code> with code>R*/code>./p>p>We start with a type code>A/code>. Then we do code>R*/code>, which gives us the object code>rStarA/code> in the slice category, which you will recall is just code>_._1/code> of type code>(R,A) > R/code>. Then we go back to types via code>Π_R(rStarA)/code> which gives us a dependent type code>P/code> inhabited by functions code>p: R > (R,A)/code>. Now, this looks a lot like an action in the code>State/code> monad. But it’s not. These code>p/code> must satisfy the property that code>_1/code> is their inverse. Which means that the code>R/code> they return must be exactly the code>R/code> they were given. So it’s like a code>State/code> action that is em>read only/em>. We can therefore simplify this to the ordinary (non-dependent) type code>R > A/code>. And now we have our code>Reader/code> monad./p>h2>Constructing the comonad/h2>p>But what about the other way around? What is the comonad constructed by composing code>R*/code> with code>Π_R/code>? Well, since we end up in the slice category, our comonad is actually in that category rather than in em>Set/em>./p>p>We start with an object code>q: A > R/code> in the slice category. Then we go to types by doing code>Π_R(q)/code>. This gives us a dependent type code>P_A/code> which is inhabited by all code>p: R > A/code> such that code>q/code> is their inverse. Then we take code>rStarΠ_R(q)/code> to go back to the slice category and we find ourselves at an object code>f: (R, Π_R(q)) > R/code>, which you’ll recall is implemented as code>_._1/code>. As an endofunctor in em>Set/R/em>, code>λq. rStarΠ_R(q)/code> takes all code>q: A > R/code> to code>p: (R, R > A) > R _._1/code> such that code>p/code> is only defined on code>R > A/code> arguments whose inverse is code>q/code>./p>p>That is, the counit for this comonad on elements code>y: A > R/code> must be a function code>counit: (R, Π_R(y)) > A/code> such that for code>_._1: (R, Π_R(y)) > R/code>, the property code>y compose counit _._1/code> holds. Note that this means that the code>R/code> returned by code>_._1/code> and the code>R/code> returned by code>y/code> must be the same. Recall that code>_._1/code> always returns the first element of its argument, and also recall that the functions in code>Π_R(y)/code> must have code>y/code> as their inverse, so they’re only defined at the first element of the argument to code>_._1/code>. That is code>p._2(x)/code> is only defined when code>x p._1/code>./p>p>If we try to encode that in Scala (ignoring all the “such that”), we get something like:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>p/span>span classk>:/span> span classo>(/span>span classkt>R/span>span classo>,/span> span classkt>R/span> span classo>>/span> span classn>A/span>span classo>))/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>p/span>span classo>./span>span classn>_2/span>span classo>(/span>span classn>p/span>span classo>./span>span classn>_1/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This looks a lot like a code>counit/code> for the code>Store/code> comonad! Except what we constructed is not that. Because of the additional requirements imposed by our functors and by the slice category, the second element of code>p/code> can only take an argument that is exactly the first element of code>p/code>. So we can simplify that to code>(R, () > A)/code> or just code>(R, A)/code>. And we now have the familiar code>Coreader/code> comonad./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/23/a-scala-comonad-tutorial/>A Scala Comonad Tutorial, Part 1/a>/h1> p classmeta> time classentry-date datetime2015-06-23T01:15:47-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>23/span>span classdate-suffix>rd/span>, span classdate-year>2015/span>/span> span classtime>1:15 am/span>/time> /p> /header> div classentry-content>p>In chapter 11 of a hrefhttp://manning.com/bjarnason>our book/a>, we talk about monads in Scala. This finally names a pattern that the reader has seen throughout the book and gives it a formal structure. We also give some intuition for what it em>means/em> for something to be a monad. Once you have this concept, you start recognizing it everywhere in the daily business of programming./p>p>Today I want to talk about em>comonads/em>, which are the dual of monads. The utility of comonads in everyday life is not quite as immediately obvious as that of monads, but they definitely come in handy sometimes. Particularly in applications like image processing and scientific computation./p>h2>A monad, upside-down/h2>p>Let’s remind ourselves of what a monad is. A monad is a functor, which just means it has a code>map/code> method:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Functor/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>B/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This has to satisfy the law that code>map(x)(a > a) x/code>, i.e. that mapping the identity function over our functor is a no-op./p>h3>Monads/h3>p>A monad is a functor code>M/code> equipped with two additional polymorphic functions; One from code>A/code> to code>MA/code> and one from code>MMA/code> to code>MA/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Monad/span>span classo>/span>span classkt>M/span>span classo>/span>span classk>_/span>span classo>/span> span classnc>extends/span> span classnc>Functor/span>span classo>/span>span classkt>M/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline> span classk>def/span> span classn>join/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>mma/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>M/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Recall that code>join/code> has to satisfy associativity, and code>unit/code> has to be an identity for code>join/code>./p>p>In Scala a monad is often stated in terms of code>flatMap/code>, which is code>map/code> followed by code>join/code>. But I find this formulation easier to explain./p>p>Every monad has the above operations, the so-called em>proper morphisms/em> of a monad, and may also bring to the table some em>nonproper morphisms/em> which give the specific monad some additional capabilities./p>h4>Reader monad/h4>p>For example, the code>Reader/code> monad brings the ability to ask for a value:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Reader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>run/span>span classk>:/span> span classkt>R/span> span classo>>/span> span classn>A/span>span classo>)/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ask/span>span classo>/span>span classkt>R/span>span classo>/span>span classk>:/span> span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>R/span>span classo>/span> span classk>/span> span classnc>Reader/span>span classo>(/span>span classn>r/span> span classk>>/span> span classn>r/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the reader monad is to pass the same context of type code>R/code> to both the outer scope and the inner scope:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>r/span>span classk>:/span> span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span>/span>span classline> span classnc>Reader/span>span classo>((/span>span classn>c/span>span classk>:/span>span classkt>R/span>span classo>)/span> span classk>>/span> span classn>r/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>c/span>span classo>)./span>span classn>run/span>span classo>(/span>span classn>c/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>Writer monad/h4>p>The code>Writer/code> monad has the ability to write a value on the side:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Writer/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>(/span>span classn>value/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>log/span>span classk>:/span> span classkt>W/span>span classo>)/span>/span>span classline>/span>span classline>span classk>def/span> span classn>tell/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>W/span>span classo>)/span>span classk>:/span> span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>Unit/span>span classo>/span> span classk>/span> span classnc>Writer/span>span classo>((),/span> span classn>w/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the writer monad is to concatenate the “log” of written values using the monoid for code>W/code> (this is using the code>Monoid/code> class from a hrefhttp://github.com/scalaz/scalaz>Scalaz/a>):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>)/span> span classk>/span>/span>span classline> span classnc>Writer/span>span classo>(/span>span classn>w/span>span classo>./span>span classn>value/span>span classo>./span>span classn>value/span>span classo>,/span> span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>append/span>span classo>(/span>span classn>w/span>span classo>./span>span classn>log/span>span classo>,/span> span classn>w/span>span classo>./span>span classn>value/span>span classo>./span>span classn>log/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And the meaning of code>unit/code> is to write the “empty” log:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classk>/span> span classnc>Writer/span>span classo>(/span>span classn>a/span>span classo>,/span> span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>zero/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>State monad/h4>p>The code>State/code> monad can both get and set the state:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>get/span>span classo>/span>span classkt>S/span>span classo>/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>S/span>span classo>/span> span classk>/span> span classnc>State/span>span classo>(/span>span classn>s/span> span classk>>/span> span classo>(/span>span classn>s/span>span classo>,/span> span classn>s/span>span classo>))/span>/span>span classline>span classk>def/span> span classn>put/span>span classo>/span>span classkt>S/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>S/span>span classo>)/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>Unit/span>span classo>/span> span classk>/span> span classnc>State/span>span classo>(/span>span classk>_/span> span classk>>/span> span classo>((),/span> span classn>s/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the state monad is to give the outer action an opportunity to get and put the state, then do the same for the inner action, making sure any subsequent actions see the changes made by previous ones./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>run/span>span classk>:/span> span classkt>S/span> span classo>>/span> span classo>(/span>span classn>A/span>span classo>,/span> span classn>S/span>span classo>))/span>/span>span classline>/span>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>v1/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>State/span>span classo>(/span>span classn>s1/span> span classk>>/span> span classo>{/span>/span>span classline> span classk>val/span> span classo>(/span>span classn>v2/span>span classo>,/span> span classn>s2/span>span classo>)/span> span classk>/span> span classn>v1/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>s1/span>span classo>)/span>/span>span classline> span classn>v2/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>s2/span>span classo>)/span>/span>span classline> span classo>})/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>Option monad/h4>p>The code>Option/code> monad can terminate without an answer:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>none/span>span classo>/span>span classkt>A/span>span classo>/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>None/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>That’s enough examples of monads. Let’s now turn to comonads./p>h2>Comonads/h2>p>A comonad is the same thing as a monad, only backwards:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Comonad/span>span classo>/span>span classkt>W/span>span classo>/span>span classk>_/span>span classo>/span> span classnc>extends/span> span classnc>Functor/span>span classo>/span>span classkt>W/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>wa/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>W/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that counit is pronounced “co-unit”, not “cow-knit”. It’s also sometimes called code>extract/code> because it allows you to get a value of type code>A/code> em>out of/em> a code>WA/code>. While with monads you can generally only put values in and not get them out, with comonads you can generally only get them out and not put them in./p>p>And instead of being able to code>join/code> two levels of a monad into one, we can code>duplicate/code> one level of a comonad into two./p>p>Kind of weird, right? This also has to obey some laws. We’ll get to those later on, but let’s first look at some actual comonads./p>h3>The identity comonad/h3>p>A simple and obvious comonad is the dumb wrapper (the identity comonad):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Id/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Id/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classnc>Id/span>span classo>(/span>span classn>f/span>span classo>(/span>span classn>a/span>span classo>))/span>/span>span classline> span classk>def/span> span classn>counit/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>a/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Id/span>span classo>/span>span classkt>Id/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>Id/span>span classo>(/span>span classk>this/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This one is also the identity em>monad/em>. code>Id/code> doesn’t have any functionality other than the proper morphisms of the (co)monad and is therefore not terribly interesting. We can get the value out with our code>counit/code>, and we can vacuously code>duplicate/code> by decorating our existing code>Id/code> with another layer./p>h3>The reader comonad/h3>p>There’s a comonad with the same capabilities as the reader monad, namely that it allows us to ask for a value:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>extract/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>ask/span>span classk>:/span> span classkt>R/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>B/span>span classo>/span> span classk>/span> span classnc>Coreader/span>span classo>(/span>span classn>f/span>span classo>(/span>span classn>extract/span>span classo>),/span> span classn>ask/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>, span classkt>Coreader/span>span classo>/span>span classkt>R/span>, span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Coreader/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>ask/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>It should be obvious how we can give a code>Comonad/code> instance for this (I’m using the a hrefhttps://github.com/non/kind-projector>Kind Projector compiler plugin/a> to make the syntax look a little nicer than Vanilla Scala):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>coreaderComonad/span>span classo>/span>span classkt>R/span>span classo>/span>span classk>:/span> span classkt>Comonad/span>span classo>/span>span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>?/span>span classo>/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>?/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span> span classk>/span> span classn>c/span> span classn>map/span> span classn>f/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span> span classn>c/span>span classo>./span>span classn>extract/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span> span classn>c/span>span classo>./span>span classn>duplicate/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Arguably, this is much more straightforward in Scala than the reader monad. In the reader em>monad/em>, the code>ask/code> function is the identity function. That’s saying “once the code>R/code> value is available, return it to me”, making it available to subsequent code>map/code> and code>flatMap/code> operations. But in code>Coreader/code>, we don’t have to pretend to have an code>R/code> value. It’s just right there and we can look at it./p>p>So code>Coreader/code> just wraps up some value of type code>A/code> together with some additional context of type code>R/code>. Why is it important that this is a em>comonad/em>? What is the meaning of code>duplicate/code> here?/p>p>To see the meaning of code>duplicate/code>, notice that it puts the whole code>Coreader/code> in the value slot (in the code>extract/code> portion). So any subsequent code>extract/code> or code>map/code> operation will be able to observe both the value of type code>A/code> and the context of type code>R/code>. We can think of this as passing the context along to those subsequent operations, which is analogous to what the reader monad does./p>p>In fact, just like code>map/code> followed by code>join/code> is usually expressed as code>flatMap/code>, by the same token code>duplicate/code> followed by code>map/code> is usually expressed as a single operation, code>extend/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>extract/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>ask/span>span classk>:/span> span classkt>R/span>span classo>)/span> span classo>{/span>/span>span classline> span classo>.../span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>duplicate/span> span classn>map/span> span classn>f/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Notice that the type signature of code>extend/code> looks like code>flatMap/code> with the direction of code>f/code> reversed. And just like we can chain operations in a monad using code>flatMap/code>, we can chain operations in a comonad using code>extend/code>. In code>Coreader/code>, code>extend/code> is making sure that code>f/code> can use the context of type code>R/code> to produce its code>B/code>./p>p>Chaining operations this way using code>flatMap/code> in a monad is sometimes called em>Kleisli composition/em>, and chaining operations using code>extend/code> in a comonad is called em>coKleisli/em> composition (or just Kleisli composition in a comonad)./p>p>The name code>extend/code> refers to the fact that it takes a “local” computation that operates on some structure and “extends” that to a “global” computation that operates on all substructures of the larger structure./p>h3>The writer comonad/h3>p>Just like the writer monad, the writer comonad can append to a log or running tally using a monoid. But instead of keeping the log always available to be appended to, it uses the same trick as the reader monad by building up an operation that gets executed once a log becomes available:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cowriter/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>tell/span>span classk>:/span> span classkt>W/span> span classo>>/span> span classn>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>B/span>span classo>/span> span classk>/span> span classnc>Cowriter/span>span classo>(/span>span classn>tell/span> span classn>andThen/span> span classn>f/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extract/span> span classk>/span> span classn>tell/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>zero/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>, span classkt>Cowriter/span>span classo>/span>span classkt>W/span>, span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cowriter/span>span classo>(/span>span classn>w1/span> span classk>>/span> span classnc>Cowriter/span>span classo>(/span>span classn>w2/span> span classk>>/span> span classn>tell/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>append/span>span classo>(/span>span classn>w1/span>span classo>,/span> span classn>w2/span>span classo>))))/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>duplicate/span> span classn>map/span> span classn>f/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that code>duplicate/code> returns a whole code>Cowriter/code> from its constructed code>run/code> function, so the meaning is that subsequent operations (composed via code>map/code> or code>extend/code>) have access to exactly one code>tell/code> function, which appends to the existing log or tally. For example, code>foo.extend(_.tell(hi))/code> will append code>hi/code> to the log of code>foo/code>./p>h2>Comonad laws/h2>p>The comonad laws are analogous to the monad laws:/p>ol>li>Left identity: code>wa.duplicate.extract wa/code>/li>li>Right identity: code>wa.extend(extract) wa/code>/li>li>Associativity: code>wa.duplicate.duplicate wa.extend(duplicate)/code>/li>/ol>p>It can be hard to get an intuition for what these laws em>mean/em>, but in short they mean that (co)Kleisli composition in a comonad should be associative and that code>extract/code> (a.k.a. code>counit/code>) should be an identity for it./p>p>Very informally, both the monad and comonad laws mean that we should be able to compose our programs top-down or bottom-up, or any combination thereof, and have that mean the same thing regardless./p>h2>Next time…/h2>p>In a hrefhttp://blog.higher-order.com/blog/2015/10/04/scala-comonad-tutorial-part-2/>part 2/a> we’ll look at some more examples of comonads and follow some of the deeper connections. Like what’s the relationship between the reader monad and the reader comonad, or the writer monad and the writer comonad? They’re not identical, but they seem to do all the same things. Are they equivalent? Isomorphic? Something else?/p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/18/easy-performance-wins-with-scalaz/>Easy Performance Wins With Scalaz/a>/h1> p classmeta> time classentry-date datetime2015-06-18T15:09:21-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>18/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>3:09 pm/span>/time> /p> /header> div classentry-content>p>I’ve found that if I’m using code>scala.concurrent.Future/code> in my code, I can get some really easy performance gains by just switching to code>scalaz.concurrent.Task/code> instead, particularly if I’m chaining them with code>map/code> or code>flatMap/code> calls, or with code>for/code> comprehensions./p>h2>Jumping into thread pools/h2>p>Every code>Future/code> is basically some work that needs to be submitted to a thread pool. When you call code>futureA.flatMap(a > futureB)/code>, both code>FutureA/code> and code>FutureB/code> need to be submitted to the thread pool, even though they are not running concurrently and could theoretically run on the same thread. This context switching takes a bit of time./p>h2>Jumping on trampolines/h2>p>With code>scalaz.concurrent.Task/code> you have a bit more control over when you submit work to a thread pool and when you actually want to continue on the thread that is already executing a code>Task/code>. When you say code>taskA.flatMap(a > taskB)/code>, the code>taskB/code> will by default just continue running on the same thread that was already executing code>taskA/code>. If you explicitly want to dip into the thread pool, you have to say so with code>Task.fork/code>./p>p>This works since a code>Task/code> is not a concurrently running computation. It’s a em>description/em> of a computation—a sequential list of instructions that may include instructions to submit some of the work to thread pools. The work is actually executed by a tight loop in code>Task/code>’s code>run/code> method. This loop is called a em>trampoline/em> since every step in the code>Task/code> (that is, every subtask) returns control to this loop./p>p>Jumping on a trampoline is a lot faster than jumping into a thread pool, so whenever we’re composing code>Future/code>s with code>map/code> and code>flatMap/code>, we can just switch to code>Task/code> and make our code faster./p>h2>Making fewer jumps/h2>p>But sometimes we know that we want to continue on the same thread and we don’t want to spend the time jumping on a trampoline at every step. To demonstrate this, I’ll use the Ackermann function. This is not necessarily a good use case for code>Future/code> but it shows the difference well./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classc1>// Only defined for positive `m` and `n`/span>/span>span classline>span classk>def/span> span classn>ackermann/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>n/span> span classo>+/span> span classmi>1/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>ackermann/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classn>ackermann/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>ackermann/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This function is supposed to terminate for all positive code>m/code> and code>n/code>, but if they are modestly large, this recursive definition overflows the stack. We could use futures to alleviate this, jumping into a thread pool instead of making a stack frame at each step:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>import/span> span classnn>scala.concurrent.Future/span>/span>span classline>span classk>import/span> span classnn>scala.concurrent.ExecutionContext.Implicits.global/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ackermannF/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Future/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classnc>Future/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>))./span>span classn>flatMap/span>span classo>(/span>span classn>identity/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classk>for/span> span classo>{/span>/span>span classline> span classn>x/span> span classk><-/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))/span>/span>span classline> span classn>y/span> span classk><-/span> span classn>x/span>/span>span classline> span classn>z/span> span classk><-/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>y/span>span classo>))/span>/span>span classline> span classn>r/span> span classk><-/span> span classn>z/span>/span>span classline> span classo>}/span> span classk>yield/span> span classn>r/span>/span>span classline> span classo>}/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Since there’s no actual concurrency going on here, we can make this instantly faster by switching to code>Task/code> instead, using a trampoline instead of a thread pool:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>import/span> span classnn>scalaz.concurrent.Task/span>span classo>,/span> span classnc>Task/span>span classo>./span>span classk>_/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ackermannT/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>now/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>))/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))./span>span classn>flatMap/span> span classo>{/span> span classn>x/span> span classk>>/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>x/span>span classo>))/span> span classo>}/span>/span>span classline> span classo>}/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But even here, we’re making too many jumps back to the trampoline with code>suspend/code>. We don’t actually need to suspend and return control to the trampoline at each step. We only need to do it enough times to avoid overflowing the stack. Let’s say we know how large our stack can grow:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>val/span> span classn>maxStack/span> span classk>/span> span classmi>512/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>We can then keep track of how many recursive calls we’ve made, and jump on the trampoline only when we need to:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>ackermannO/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>step/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>stack/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span>/span>span classline> span classk>if/span> span classo>(/span>span classn>stack/span> span classo>>/span> span classn>maxStack/span>span classo>)/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannO/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>))/span>/span>span classline> span classk>else/span> span classn>go/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>,/span> span classn>stack/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>go/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>stack/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>now/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>step/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classk>for/span> span classo>{/span>/span>span classline> span classn>internalRec/span> span classk><-/span> span classn>step/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classn>result/span> span classk><-/span> span classn>step/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>internalRec/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classo>}/span> span classk>yield/span> span classn>result/span>/span>span classline> span classo>}/span>/span>span classline> span classn>go/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>,/span> span classmi>0/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>How fast is it?/h2>p>I did some comparisons using a hrefhttps://github.com/google/caliper>Caliper/a> and made this pretty graph for you:/p>p>img src/images/futuretaskplot.png>/p>p>The horizontal axis is the number of steps, and the vertical axis is the mean time that number of steps took over a few thousand runs./p>p>This graph shows that code>Task/code> is slightly faster than code>Future/code> for submitting to thread pools (blue and yellow lines marked em>Future/em> and em>Task/em> respectively) only for very small tasks; up to about when you get to 50 steps, when (on my Macbook) both futures and tasks cross the 30 μs threshold. This difference is probably due to the fact that a code>Future/code> is a running computation while a code>Task/code> is partially constructed up front and explicitly code>run/code> later. So with the code>Future/code> the threads might just be waiting for more work. The overhead of code>Task.run/code> seems to catch up with us at around 50 steps./p>p>But honestly the difference between these two lines is not something I would care about in a real application, because if we jump on the trampoline instead of submitting to a thread pool (green line marked em>Trampoline/em>), things are em>between one and two orders of magnitude faster/em>./p>p>If we only jump on the trampoline when we really need it (red line marked em>Optimized/em>), we can gain another order of magnitude. Compared to the original naïve version that always goes to the thread pool, strong>em>this is now the difference between running your program on a 10 MHz machine and running it on a 1 GHz machine/em>/strong>./p>p>If we measure without using any code>Task/code>/code>Future/code> at all, the line tracks the em>Optimized/em> red line pretty closely then shoots to infinity around 1000 (or however many frames fit in your stack space) because the program crashes at that point./p>p>In summary, if we’re smart about trampolines vs thread pools, code>Future/code> vs code>Task/code>, and optimize for our stack size, we can go from milliseconds to microseconds with not very much effort. Or seconds to milliseconds, or weeks to hours, as the case may be./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/16/pulling-out-of-functional-programming-in-java/>Pulling Out of Functional Programming in Java/a>/h1> p classmeta> time classentry-date datetime2015-06-16T11:37:34-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>16/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:37 am/span>/time> /p> /header> div classentry-content>p>After giving it a lot of thought I have come to the conclusion that I won’t be involved in a hrefhttp://manning.com/saumont>“Functional Programming in Java”/a>. There are many reasons, including that I just don’t think I can spend the time to make this a good book. Looking at all the things I have scheduled for the rest of the year, I can’t find the time to work on it./p>p>More depressingly, the thought of spending a year or more writing another book makes me anxious. I know from experience that making a book (at least a good one) is really hard and takes up a lot of mental energy. Maybe one day there will be a book that I will want to forego a year of evenings and weekends for, but today is not that day./p>p>Originally, the content of FPiJ was going to be based on “Functional Programming in Scala”, but after some discussion with the publisher I think we were all beginning to see that this book deserved its own original content specifically on an FP style in Java./p>p>I really do think such a thing deserves its own original book. Since Java is strictly less suitable for functional programming than Scala is, a book on FP in Java will have to lay a lot of groundwork that we didn’t have to do with FPiS, and it will have to forego a lot of the more advanced topics./p>p>I wish the author of that book, and the publisher, all the best and I hope they do well. I’m sorry to let you all down, but I’m sure this is for the best./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/03/06/a-companion-booklet-to-functional-programming-in-scala/>A Companion Booklet to FPiS/a>/h1> p classmeta> time classentry-date datetime2015-03-06T15:17:35-05:00>span classdate>span classdate-month>Mar/span> span classdate-day>6/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>3:17 pm/span>/time> /p> /header> div classentry-content>p>Our book, a hrefhttp://manning.com/bjarnason>Functional Programming in Scala/a>, relies heavily on exercises. Hints and answers for those exercises are not actually in the book, but are a hrefhttp://github.com/fpinscala/fpinscala>freely available on GitHub/a> under a permissive MIT license. Likewise, we have written chapter notes that we reference throughout the book and made them a hrefhttp://github.com/fpinscala/fpinscala/wiki>available as a community-editable wiki/a>./p>p>Naturally, readers get the most out of this book by downloading the source code from GitHub and doing the exercises as they read. But a number of readers have made the comment that they wish they could have the hints and answers with them when they read the book on the train to and from work, on a long flight, or wherever there is no internet connection or it’s not convenient to use a computer./p>p>It is of course entirely possible to print out the chapter notes, hints, and exercises, and take them with you either as a hardcopy or as a PDF to use on a phone or tablet. Well, I’ve taken the liberty of doing that work for you. I wrote a little script to concatenate all the chapter notes, errata, hints, and answers into Markdown files and then just printed them all to a single document, tweaking a few things here and there. I’m calling this em>A companion booklet to “Functional Programming in Scala”/em>. It is released under the same a hrefhttps://github.com/fpinscala/fpinscala/blob/master/LICENSE>MIT license/a> as the content it aggregates. This means you’re free to copy it, distribute or sell it, or basically do whatever you want with it. The Markdown source of the manuscript is a hrefhttps://github.com/runarorama/fpiscompanion>available on my GitHub/a>./p>p>I have made a hrefhttps://leanpub.com/fpinscalacompanion>an electronic version of this booklet available on Leanpub/a> as as a PDF, ePub, and Kindle file on a pay-what-you-want basis (minimum of $0.99). It has full color syntax highlighting throughout and a few little tweaks to make it format nicely. The paper size is standard US Letter which makes it easy to print on most color printers. If you choose to buy the booklet from Leanpub, they get a small fee, a small portion of the proceeds goes to support a hrefhttp://www.libertyinnorthkorea.org/>Liberty in North Korea/a>, and the rest goes to yours truly. You’ll also get updates when those inevitably happen./p>p>If you don’t care about any of that, a href/assets/fpiscompanion.pdf>you can grab the PDF from here with my compliments/a>./p>p>The booklet is also a hrefhttps://www.createspace.com/5325404>available from CreateSpace/a> or a hrefhttp://www.amazon.com/companion-booklet-Functional-Programming-Scala/dp/1508537569>Amazon/a> as a full color printed paperback. This comes in a nicely bound glossy cover for just a little more than the price of printing (they print it on demand for you). I’ve ordered one and I’m really happy with the quality of this print:/p>p>img src/images/bookletcover.jpg>img src/images/chapternotes.jpg>img src/images/exercises.jpg>/p>p>The print version is of course under the same permissive license, so you can make copies of it, make derivative works, or do whatever you want. It’s important to note that with this booklet I’ve not done anything other than design a little cover and then em>literally print out this freely available content/em> and upload it to Amazon, which anybody could have done (and you still can if you want)./p>p>I hope this makes em>Functional Programming in Scala/em> more useful and more enjoyable for more people./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/02/08/a-better-reading-list-with-mathematica/>A Better Reading List With Mathematica/a>/h1> p classmeta> time classentry-date datetime2015-02-08T11:04:00-05:00>span classdate>span classdate-month>Feb/span> span classdate-day>8/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:04 am/span>/time> /p> /header> div classentry-content>p>Like a lot of people, I keep a list of books I want to read. And because there are a great many more books that interest me than I can possibly read in my lifetime, this list has become quite long./p>p>In the olden days of brick-and-mortar bookstores and libraries, I would discover books to read by browsing shelves and picking up what looked interesting at the time. I might even find something that I knew was on my list. “Oh, I’ve been meaning to read that!”/p>p>The Internet changes this dynamic dramatically. It makes it much easier for me to discover books that interest me, and also to access any book that I might want to read, instantly, anywhere. At any given time, I have a couple of books that I’m “currently reading”, and when I finish one I can start another immediately. I use Goodreads to manage my to-read list, and it’s easy for me to scroll through the list and pick out my next book./p>p>But again, this list is very long. So I wanted a good way to filter out books I will really never read, and sort it such that the most “important” books in some sense show up first. Then every time I need a new book I could take the first one from the list and make a binary decision: either “I will read this right now”, or “I am never reading this”. In the latter case, if a book interests me enough at a later time, I’m sure it will find its way back onto my list./p>p>The problem then is to find a good metric by which to rank books. Goodreads lets users rank books with a star-rating from 1 to 5, and presents you with an average rating by which you can sort the list. The problem is that a lot of books that interest me have only one rating and it’s 5 stars, giving the book an “average” of 5.0. So if I go with that method I will be perpetually reading obscure books that one other person has read and loved. This is not necessarily a bad thing, but I do want to branch out a bit./p>p>Another possibility is to use the number of ratings to calculate a a hrefhttp://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval>confidence interval/a> for the average rating. For example, using the a hrefhttp://www.evanmiller.org/how-not-to-sort-by-average-rating.html>Wilson score/a> I could find an upper and lower bound code>s1/code> and code>s2/code> (higher and lower than the average rating, respectively) that will let me say “I am 95% sure that any random sample of readers of an equal size would give an average rating between code>s1/code> and code>s2/code>.” I could then sort the list by the lower bound code>s1/code>./p>p>But this method is dissatisfactory for a number of reasons. First, it’s not clear how to fit star ratings to such a measure. If we do the naive thing and count a 1-star rating as 1/5 and a 5 star rating as 5/5, that counts a 1-star rating as a “partial success” in some sense. We could discard 1-stars as 0, and count 2, 3, 4, and 5 stars as 25%, 50%, 75%, and 100%, respectively./p>p>But even if we did make it fit somehow, it turns out that if you take em>any moderately popular book/em> on Goodreads at random, it will have an average rating somewhere close to 4. I could a hrefhttp://stephsun.com/silverizing.html>manufacture a prior/a> based on this knowledge and use that instead of the normal distribution or the Jeffreys prior in the confidence interval, but that would still not be a very good ranking because a hrefhttp://stephsun.com/metascores.html>reader review metascores are meaningless/a>./p>p>In the article a hrefhttp://stephsun.com/metascores.html>“Reader review metascores are meaningless”/a>, Stephanie Shun suggests using the em>percentage of 5-star ratings/em> as the relevant metric rather than the average rating. This is a good suggestion, since even a single 5-star rating carries a lot of actionable information whereas an average rating close to 4.0 carries very little./p>p>I can then use the Wilson score directly, counting a 5-star rating as a successful trial and any other rating as a failed one. I can then just use the normal distribution instead of working with an artisanally curated prior./p>p>Mathematica makes it easy to generate the Wilson score. Here, code>pos/code> is the number of positive trials (number of 5-star ratings), code>n/code> is the number of total ratings, and code>confidence/code> is the desired confidence percentage. I’m taking the lower bound of the confidence interval to get my score./p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Wilson/span>span classp>/span>span classnv>pos_/span>span classp>,/span>span classw> /span>span classnv>n_/span>span classp>,/span>span classw> /span>span classnv>confidence_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>/span>span classline>span classw> /span>span classn>If/span>span classp>/span>span classn>n/span>span classw> /span>span classo>/span>span classw> /span>span classmi>0/span>span classw> /span>span classo>||/span>span classw> /span>span classn>n/span>span classw> /span>span classerr></span>span classw> /span>span classn>pos/span>span classp>,/span>span classw> /span>span classmi>0/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>z/span>span classw> /span>span classo>/span>span classw> /span>span classn>Quantile/span>span classp>/span>span classn>NormalDistribution/span>span classp>,/span>span classw> /span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classp>(/span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classn>confidence/span>span classp>)/span>span classo>//span>span classmi>2/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>p/span>span classw> /span>span classo>/span>span classw> /span>span classn>pos/span>span classo>//span>span classn>n/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classp>(/span>span classo>-/span>span classp>(/span>span classn>z/span>span classw> /span>span classn>Sqrt/span>span classp>(/span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classp>(/span>span classmi>4/span>span classw> /span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classp>(/span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classn>p/span>span classp>)/span>span classw> /span>span classn>p/span>span classp>)/span>span classo>//span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classp>(/span>span classmi>2/span>span classw> /span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classn>p/span>span classp>)/span>span classw> /span>span classo>//span>span classw>/span>/span>span classline>span classw> /span>span classp>(/span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classn>n/span>span classw> /span>span classo>+/span>span classw> /span>span classmi>1/span>span classp>)/span>span classw>/span>/span>span classline>span classw> /span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now I just need to get the book data from Goodreads. Fortunately, a hrefhttps://www.goodreads.com/api>it has a pretty rich API/a>. I just need a developer key, which anyone can get for free./p>p>For example, to get the ratings for a given book code>id/code>, we can use their XML api for books and pattern match on the result to get the ratings by score:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Ratings/span>span classp>/span>span classnv>id_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classn>id/span>span classp>/span>span classw> /span>span classo>/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>raw/span>span classw> /span>span classo>/span>span classw> /span>span classn>Cases/span>span classp>/span>span classn>Import/span>span classp>/span>span classn>ToString/span>span classp>/span>span classn>StringForm/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"http://www.goodreads.com/book/show.xml?key``&id``"/span>span classp>,/span>span classw> /span>span classn>key/span>span classp>,/span>span classw> /span>span classn>id/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"rating_dist"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>d_/span>span classp>}/span>span classw> /span>span classo>->/span>span classw> /span>span classn>d/span>span classp>,/span>span classw> /span>span classn>Infinity/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>data/span>span classw> /span>span classo>/span>span classw> /span>span classn>StringSplit/span>span classp>/span>span classnv>#/span>span classp>,/span>span classw> /span>span classs>":"/span>span classp>/span>span classw> /span>span classo>&/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>StringSplit/span>span classp>/span>span classn>raw/span>span classp>,/span>span classw> /span>span classs>"|"/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw> /span>span classn>Block/span>span classp>{},/span>span classw> /span>span classn>Pause/span>span classp>/span>span classmi>1/span>span classp>;/span>span classw>/span>/span>span classline>span classw> /span>span classn>FromDigits/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>Association/span>span classp>/span>span classn>Rule/span>span classw> /span>span classo>@@@/span>span classw> /span>span classn>First/span>span classp>/span>span classn>data/span>span classp>;/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Here, code>key/code> is my Goodreads developer API key, defined elsewhere. I put a code>Pause1/code> in the call since Goodreads throttles API calls so you can’t make more than one call per second to each API endpoint. I’m also memoizing the result, by assigning to code>Ratingsid/code> in the global environment./p>p>code>Ratings/code> will give us an association list with the number of ratings for each score from 1 to 5, together with the total. For example, for the first book in their catalogue, em>Harry Potter and the Half-Blood Prince/em>, here are the scores:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>In/span>span classp>/span>span classmi>1/span>span classp>/span>span classo>:/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classmi>1/span>span classp>/span>span classw>/span>/span>span classline>/span>span classline>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classo>/span>span classw> /span>span classerr></span>span classo>|/span>span classs>"5"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>782740/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"4"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>352725/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"3"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>111068/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"2"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>17693/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"1"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>5289/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"total"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>1269515/span>span classo>|/span>span classerr>>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Sweet. Let’s see how Harry Potter #6 would score with our rating:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>In/span>span classp>/span>span classmi>2/span>span classp>/span>span classo>:/span>span classw> /span>span classn>Wilson/span>span classp>/span>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classs>"5"/span>span classp>,/span>span classw> /span>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classs>"total"/span>span classp>,/span>span classw> /span>span classmf>0.95/span>span classp>/span>span classw>/span>/span>span classline>/span>span classline>span classn>Out/span>span classp>/span>span classmi>2/span>span classp>/span>span classo>/span>span classw> /span>span classmf>0.61572/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>So Wilson is 95% confident that in any random sample of about 1.2 million Harry Potter readers, at least 61.572% of them would give em>The Half-Blood Prince/em> a 5-star rating. That turns out to be a pretty high score, so if this book were on my list (which it isn’t), it would feature pretty close to the very top./p>p>But now the score for a relatively obscure title is too low. For example, the lower bound of the 95% confidence interval for a single-rating 5-star book will be 0.206549, which will be towards the bottom of any list. This means I would never get to any of the obscure books on my reading list, since they would be edged out by moderately popular books with an average rating close to 4.0./p>p>See, if I’ve picked a book that em>I want to read/em>, I’d consider five ratings that are all five stars a much stronger signal than the fact that people who like Harry Potter enough to read 5 previous books loved the 6th one. Currently the 5*5 book will score 57%, a bit weaker than the Potter book’s 62%./p>p>I can fix this by lowering the confidence level. Because honestly, I don’t need a high confidence in the ranking. I’d rather err on the side of picking up a deservedly obscure book than to miss out on a rare gem. Experimenting with this a bit, I find that a confidence around 80% raises the obscure books enough to give me an interesting mix. For example, a 5*5 book gets a 75% rank, while the Harry Potter one stays at 62%./p>p>I’m going to call that the em>Rúnar rank/em> of a given book. The Rúnar rank is defined as the lower bound of the em>1-1/q/em> Wilson confidence interval for scoring in the em>q/em>th em>q/em>-quantile. In the special case of Goodreads ratings, it’s the 80% confidence for a 5-star rating./p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>RunarRank/span>span classp>/span>span classnv>id_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>With/span>span classp>{/span>span classn>ratings/span>span classw> /span>span classo>/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classn>id/span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classn>Wilson/span>span classp>/span>span classn>ratings/span>span classp>/span>span classs>"5"/span>span classp>,/span>span classw> /span>span classn>ratings/span>span classp>/span>span classs>"total"/span>span classp>,/span>span classw> /span>span classmf>.8/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Unfortunately, there’s no way to get the rank of all the books in my reading list in one call to the Goodreads API. And when I asked them about it they basically said “you can’t do that”, so I’m assuming that feature will not be added any time soon. So I’ll have to get the reading list first, then call code>RunarRank/code> for each book’s code>id/code>. In Goodreads, books are managed by “shelves”, and the API allows getting the contents of a given shelf, 200 books at a time:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>GetShelf/span>span classp>/span>span classnv>user_/span>span classp>,/span>span classw> /span>span classnv>shelf_/span>span classp>/span>span classw> /span>span classo>:/span>span classw>/span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classn>raw/span>span classw> /span>span classo>/span>span classw> /span>/span>span classline>span classw> /span>span classn>Cases/span>span classp>/span>span classn>Import/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>ToString/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>StringForm/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classerr>"/span>span classn>http/span>span classerr>:/span>span classo>///span>span classn>www/span>span classerr>./span>span classn>goodreads/span>span classerr>./span>span classn>com/span>span classo>//span>span classn>review/span>span classo>//span>span classn>list/span>span classerr>./span>span classn>xml/span>span classo>?/span>span classn>v/span>span classo>/span>span classmi>2/span>span classo>&/span>span classn>key/span>span classo>/span>span classerr>``/span>span classo>&/span>span classn>id/span>span classo>/span>span classerr>``/span>span classo>&/span>span classerr>\/span>span classw>/span>/span>span classline>span classn>shelf/span>span classo>/span>span classerr>``/span>span classo>&/span>span classn>sort/span>span classo>/span>span classnv>avg_rating/span>span classo>&/span>span classn>order/span>span classo>/span>span classn>d/span>span classo>&/span>span classnv>per_page/span>span classo>/span>span classmi>200/span>span classerr>"/span>span classp>,/span>span classw> /span>span classn>key/span>span classp>,/span>span classw> /span>span classn>user/span>span classp>,/span>span classw> /span>span classn>shelf/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"book"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>___/span>span classp>,/span>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>id_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"title"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>title_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"average_rating"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>avg_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"authors"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"author"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"name"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>author_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>}/span>span classw> /span>span classo>->/span>span classw> /span>span classp>{/span>span classs>"id"/span>span classw> /span>span classo>->/span>span classw> /span>/span>span classline>span classw> /span>span classn>id/span>span classp>,/span>span classw> /span>span classs>"title"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>title/span>span classp>,/span>span classw> /span>span classs>"author"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>author/span>span classp>,/span>span classw> /span>span classs>"avg"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>avg/span>span classp>},/span>span classw> /span>/span>span classline>span classw> /span>span classn>Infinity/span>span classp>},/span>span classw> /span>span classn>Association/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>raw/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>I’m doing a bunch of XML pattern matching here to get the code>id/code>, code>title/code>, code>average_rating/code>, and first code>author/code> of each book. Then I put that in an association list. I’m getting only the top-200 books on the list by average rating (which currently is about half my list)./p>p>With that in hand, I can get the contents of my “to-read” shelf with code>GetShelfrunar, to-read/code>, where code>runar/code> is my Goodreads user id. And given that, I can call code>RunarRank/code> on each book on the shelf, then sort the result by that rank:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>RunarSort/span>span classp>/span>span classnv>shelf_/span>span classp>/span>span classw> /span>span classo>:/span>span classw>/span>/span>span classline>span classw> /span>span classn>Sort/span>span classp>/span>span classn>Map/span>span classp>/span>span classn>Function/span>span classp>/span>span classn>x/span>span classp>,/span>span classw> /span>span classn>Append/span>span classp>/span>span classn>x/span>span classp>,/span>span classw> /span>span classs>"rank"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>RunarRank/span>span classp>/span>span classn>x/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>shelf/span>span classp>,/span>span classw> /span>span classnv>#1/span>span classp>/span>span classs>"rank"/span>span classp>/span>span classw> /span>span classerr>>/span>span classw> /span>span classnv>#2/span>span classp>/span>span classs>"rank"/span>span classp>/span>span classw> /span>span classo>&/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>To get the ranked reading list of any user:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>ReadingList/span>span classp>/span>span classnv>user_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>RunarSort/span>span classp>/span>span classn>GetShelf/span>span classp>/span>span classn>user/span>span classp>,/span>span classw> /span>span classs>"to-read"/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And to print it out nicely:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Gridify/span>span classp>/span>span classnv>books_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>/span>span classline>span classw> /span>span classn>Grid/span>span classp>/span>span classn>Flatten/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>Cases/span>span classp>/span>span classn>books/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classnv>b_/span>span classw> /span>span classo>->/span>span classw> /span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classp>{/span>span classn>b/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"title"/span>span classp>,/span>span classw> /span>span classn>UnitConvert/span>span classp>/span>span classn>b/span>span classp>/span>span classs>"rank"/span>span classp>,/span>span classw> /span>span classs>"Percent"/span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classp>{/span>span classs>""/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"author"/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"avg"/span>span classp>},/span>span classw> /span>span classp>{/span>span classs>""/span>span classp>,/span>span classw> /span>span classs>""/span>span classp>,/span>span classw> /span>span classs>""/span>span classp>}/span>span classw> /span>span classp>},/span>span classw> /span>span classmi>1/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classn>Alignment/span>span classw> /span>span classo>->/span>span classw> /span>span classn>Left/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now I can get, say, the first 10 books on my improved reading list:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Gridify/span>span classp>/span>span classn>ReadingList/span>span classp>/span>span classn>runar/span>span classp>/span>span classmi>1/span>span classw> /span>span classo>;;/span>span classw> /span>span classmi>10/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>table>thead>tr>th styletext-align:left;> /th>th styletext-align:left;> /th>th styletext-align:right;> /th>/tr>/thead>tbody>tr>td styletext-align:left;> 9934419 /td>td styletext-align:left;> Kvæðasafn /td>td styletext-align:right;> 75.2743% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Snorri Hjartarson /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 17278 /td>td styletext-align:left;> The Feynman Lectures on Physics Vol 1 /td>td styletext-align:right;> 67.2231% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Richard P. Feynman /td>td styletext-align:right;> 4.58 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 640909 /td>td styletext-align:left;> The Knowing Animal: A Philosophical Inquiry Into Knowledge and Truth /td>td styletext-align:right;> 64.6221% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Raymond Tallis /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 640913 /td>td styletext-align:left;> The Hand: A Philosophical Inquiry Into Human Being /td>td styletext-align:right;> 64.6221% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Raymond Tallis /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 4050770 /td>td styletext-align:left;> Volition As Cognitive Self Regulation /td>td styletext-align:right;> 62.231% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Harry Binswanger /td>td styletext-align:right;> 4.86 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 8664353 /td>td styletext-align:left;> Unbroken: A World War II Story of Survival, Resilience, and Redemption /td>td styletext-align:right;> 60.9849% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Laura Hillenbrand /td>td styletext-align:right;> 4.45 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 13413455 /td>td styletext-align:left;> Software Foundations /td>td styletext-align:right;> 60.1596% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Benjamin C. Pierce /td>td styletext-align:right;> 4.80 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 77523 /td>td styletext-align:left;> Harry Potter and the Sorcerer’s Stone (Harry Potter #1) /td>td styletext-align:right;> 59.1459% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> J.K. Rowling /td>td styletext-align:right;> 4.39 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 13539024 /td>td styletext-align:left;> Free Market Revolution: How Ayn Rand’s Ideas Can End Big Government /td>td styletext-align:right;> 59.1102% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Yaron Brook /td>td styletext-align:right;> 4.48 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 1609224 /td>td styletext-align:left;> The Law /td>td styletext-align:right;> 58.767% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Frédéric Bastiat /td>td styletext-align:right;> 4.40 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>/tbody>/table>p>I’m quite happy with that. Some very popular and well-loved books interspersed with obscure ones with exclusively (or almost exclusively) positive reviews. The most satisfying thing is that the rating carries a real meaning. It’s basically the relative likelihood that I will enjoy the book enough to rate it five stars./p>p>I can test this ranking against books I’ve already read. Here’s the top of my “read” shelf, according to their Rúnar Rank:/p>table>thead>tr>th styletext-align:left;> /th>th styletext-align:left;> /th>th styletext-align:right;> /th>/tr>/thead>tbody>tr>td styletext-align:left;>17930467/td>td styletext-align:left;>The Fourth Phase of Water/td>td styletext-align:right;>68.0406%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Gerald H. Pollack/td>td styletext-align:right;>4.85/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>7687279/td>td styletext-align:left;>Nothing Less Than Victory: Decisive Wars and the Lessons of History/td>td styletext-align:right;>64.9297%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>John David Lewis/td>td styletext-align:right;>4.67/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>43713/td>td styletext-align:left;>Structure and Interpretation of Computer Programs/td>td styletext-align:right;>62.0211%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Harold Abelson/td>td styletext-align:right;>4.47/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>7543507/td>td styletext-align:left;>Capitalism Unbound: The Incontestable Moral Case for Individual Rights/td>td styletext-align:right;>57.6085%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Andrew Bernstein/td>td styletext-align:right;>4.67/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>13542387/td>td styletext-align:left;>The DIM Hypothesis: Why the Lights of the West Are Going Out/td>td styletext-align:right;>55.3296%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Leonard Peikoff/td>td styletext-align:right;>4.37/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>5932/td>td styletext-align:left;>Twenty Love Poems and a Song of Despair/td>td styletext-align:right;>54.7205%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Pablo Neruda/td>td styletext-align:right;>4.36/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>18007564/td>td styletext-align:left;>The Martian/td>td styletext-align:right;>53.9136%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Andy Weir/td>td styletext-align:right;>4.36/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>24113/td>td styletext-align:left;>Gödel, Escher, Bach: An Eternal Golden Braid/td>td styletext-align:right;>53.5588%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Douglas R. Hofstadter/td>td styletext-align:right;>4.29/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>19312/td>td styletext-align:left;>The Brothers Lionheart/td>td styletext-align:right;>53.0952%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Astrid Lindgren/td>td styletext-align:right;>4.33/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>13541678/td>td styletext-align:left;>Functional Programming in Scala/td>td styletext-align:right;>52.6902%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Rúnar Bjarnason/td>td styletext-align:right;>4.54/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>/tbody>/table>p>That’s perfect. Those are definitely books I thouroughly enjoyed and would heartily recommend. Especially that last one./p>p>I’ve published this function as a Wolfram Cloud API, and you can call it at a hrefhttps://www.wolframcloud.com/app/objects/4f4a7b3c-38a5-4bf3-81b6-7ca8e05ea100>https://www.wolframcloud.com/app/objects/4f4a7b3c-38a5-4bf3-81b6-7ca8e05ea100/a>. It takes two URL query parameters, code>key/code> and code>user/code>, which are your Goodreads API key and the Goodreads user ID whose reading list you want to generate, respectively. Enjoy!/p>/div> /article> article> header> h1 classentry-title>a href/blog/2014/12/21/maximally-powerful/>Maximally Powerful, Minimally Useful/a>/h1> p classmeta> time classentry-date datetime2014-12-21T23:23:00-05:00>span classdate>span classdate-month>Dec/span> span classdate-day>21/span>span classdate-suffix>st/span>, span classdate-year>2014/span>/span> span classtime>11:23 pm/span>/time> /p> /header> div classentry-content>p>It’s well known that there is a trade-off in language and systems design between expressiveness and analyzability. That is, the more expressive a language or system is, the less we can reason about it, and vice versa. The more capable the system, the less comprehensible it is./p>p>This principle is very widely applicable, and it’s a useful thing to keep in mind when designing languages and libraries. A practical implication of being aware of this principle is that we always make components exactly as expressive as necessary, but no more. This maximizes the ability of any downstream systems to reason about our components. And dually, for things that we receive or consume, we should require exactly as much analytic power as necessary, and no more. That maximizes the expressive freedom of the upstream components./p>p>I find myself thinking about this principle a lot lately, and seeing it more or less everywhere I look. So I’m seeking a more general statement of it, if such a thing is possible. It seems that more generally than issues of expressivity/analyzability, a restriction at one semantic level translates to freedom and power at another semantic level./p>p>What I want to do here is give a whole bunch of examples. Then we’ll see if we can come up with an integration for them all. This is all written as an exercise in thinking out loud and is not to be taken very seriously./p>h2>Examples from computer science/h2>h3>Context-free and regular grammars/h3>p>In formal language theory, context-free grammars are more expressive than regular grammars. The former can describe strictly more sets of strings than the latter. On the other hand, it’s harder to reason about context-free grammars than regular ones. For example, we can decide whether two regular expressions are equal (they describe the same set of strings), but this is undecidable in general for context-free grammars./p>h3>Monads and applicative functors/h3>p>If we know that an applicative functor is a monad, we gain some expressive power that we don’t get with just an applicative functor. Namely, a monad is an applicative functor with an additional capability: monadic join (or “bind”, or “flatMap”). That is, context-sensitivity, or the ability to bind variables in monadic expressions./p>p>This power comes at a cost. Whereas we can always compose any two applicatives to form a composite applicative, two monads do not in general compose to form a monad. It may be the case that a given monad composes with any other monad, but we need some additional information about it in order to be able to conclude that it does./p>h3>Actors and futures/h3>p>Futures have an algebraic theory, so we can reason about them algebraically. Namely, they form an applicative functor which means that two futures code>x/code> and code>y/code> make a composite future that does code>x/code> and code>y/code> in parallel. They also compose sequentially since they form a monad./p>p>Actors on the other hand have no algebraic theory and afford no algebraic reasoning of this sort. They are “fire and forget”, so they could potentially do anything at all. This means that actor systems can do strictly more things in more ways than systems composed of futures, but our ability to reason about such systems is drastically diminished./p>h3>Typed and untyped programming/h3>p>When we have an untyped function, it could receive any type of argument and produce any type of output. The implementation is totally unrestricted, so that gives us a great deal of expressive freedom. Such a function can potentially participate in a lot of different expressions that use the function in different ways./p>p>A function of type code>Bool -> Bool/code> however is highly restricted. Its argument can only be one of two things, and the result can only be one of two things as well. So there are 4 different implementations such a function could possibly have. Therefore this restriction gives us a great deal of analyzability./p>p>For example, since the argument is of type code>Bool/code> and not code>Any/code>, the implementation mostly writes itself. We need to consider only two possibilities. code>Bool/code> (a type of size 2) is fundamentally easier to reason about than code>Any/code> (a type of potentially infinite size). Similarly, any usage of the function is easy to reason about. A caller can be sure not to call it with arguments other than code>True/code> or code>False/code>, and enlist the help of a type system to guarantee that expressions involving the function are meaningful./p>h3>Total functional programming/h3>p>Programming in non-total languages affords us the power of general recursion and “fast and loose reasoning” where we can transition between valid states through potentially invalid ones. The cost is, of course, the halting problem. But more than that, we can no longer be certain that our programs are em>meaningful/em>, and we lose some algebraic reasoning. For example, consider the following:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code class>span classline>map (- n) (map (+ n) xs)) xs/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This states that adding code>n/code> to every number in a list and then subtracting code>n/code> again should be the identity. But what if code>n/code> actually throws an exception or never halts? In a non-total language, we need some additional information. Namely, we need to know that code>n/code> is total./p>h3>Referential transparency and side effects/h3>p>The example above also serves to illustrate the trade-off between purely functional and impure programming. If code>n/code> could have arbitrary side effects, algebraic reasoning of this sort involving code>n/code> is totally annihilated. But if we know that code>n/code> is referentially transparent, algebraic reasoning is preserved. The power of side effects comes at the cost of algebraic reasoning. This price includes loss of compositionality, modularity, parallelizability, and parametricity. Our programs can do strictly more things, but we can conclude strictly fewer things about our programs./p>h2>Example from infosec/h2>p>There is a principle in computer security called em>The Principle of Least Privilege/em>. It says that a user or program should have exactly as much authority as necessary but no more. This constrains the power of the entity, but greatly enhances the power of others to predict and reason about what the entity is going to do, resulting in the following benefits:/p>ul>li>strong>Compositionality/strong> – The fewer privileges a component requires, the easier it is to deploy inside a larger environment. For the purposes of safety, higher privileges are a barrier to composition since a composite system requires the em>highest/em> privileges of any of its components./li>li>strong>Modularity/strong> – A component with restricted privileges is easier to reason about in the sense that its interaction with other components will be limited. We can reason mechanically about where this limit actually is, which gives us better guarantees about the the security and stability of the overall system. A restricted component is also easier to test in isolation, since it can be run inside an overall restricted environment./li>/ul>h2>Example from politics/h2>p>Some might notice an analogy between the Principle of Least Privilege and the idea of a constitutionally limited government. An absolute dictatorship or pure democracy will have absolute power to enact whatever whim strikes the ruler or majority at the moment. But the overall stability, security, and freedom of the people is greatly enhanced by the presence of legal limits on the power of the government. A limited constitutional republic also makes for a better neighbor to other states./p>p>More generally, a ban on the initiation of physical force by one citizen against another, or by the government against citizens, or against other states, makes for a peaceful and prosperous society. The “cost” of such a system is the inability of one person (or even a great number of people) to impose their preferences on others by force./p>h2>An example from mathematics/h2>p>The framework of two-dimensional Euclidean geometry is simply an empty page on which we can construct lines and curves using tools like a compass and straightedge. When we go from that framework to a Cartesian one, we constrain ourselves to reasoning on a grid of pairs of numbers. This is a tradeoff between expressivity and analyzability. When we move fom Euclidean to Cartesian geometry, we lose the ability to assume isotropy of space, intersection of curves, and compatibility between dimensions. But we gain much more powerful things through the restriction: the ability to precisely define geometric objects, to do arithmetic with them, to generalize to higher dimensions, and to reason with higher abstractions like linear algebra and category theory./p>h2>Examples from everyday life/h2>h3>Driving on roads/h3>p>Roads constrain the routes we can take when we drive or walk. We give up moving in a straight line to wherever we want to go. But the benefit is huge. Roads let us get to where we’re going much faster and more safely than we would otherwise./p>h3>Commodity components/h3>p>Let’s say you make a decision to have only one kind of outfit that you wear on a daily basis. You just go out and buy multiple identical outfits. Whereas you have lost the ability to express yourself by the things you wear, you have gained a certain ability to reason about your clothing. The system is also fault-tolerant and compositional!/p>h2>Summary/h2>p>What is this principle? Here are some ways of saying it:/p>ul>li>Things that are maximally general for first-order applications are minimally useful for higher-order applications, and vice versa./li>li>A language that is maximally expressive is minimally analyzable./li>li>A simplifying assumption at one semantic level paves the way to a richer structure at a higher semantic level./li>/ul>p>What do you think? Can you think of a way to integrate these examples into a general principle? Do you have other favorite examples of this principle in action? Is this something everyone already knows about and I’m just late to the party?/p>/div> /article> div classpagination> a classprev href/posts/2>← Older/a> a href/blog/archives>Blog Archives/a> /div>/div>aside classsidebar> section>h1>Read my book/h1>a hrefhttp://manning.com/bjarnason>img src/images/FPinScalaCover.png width553px height694px>/a>/section>section> h1>Recent Posts/h1> ul idrecent_posts> li classpost> a href/blog/2016/04/02/a-comonad-of-graph-decompositions/>A Comonad of Graph Decompositions/a> /li> li classpost> a href/blog/2015/10/12/freedom-and-forgetfulness/>Freedom and Forgetfulness/a> /li> li classpost> a href/blog/2015/10/04/scala-comonad-tutorial-part-2/>Scala Comonad Tutorial, Part 2/a> /li> li classpost> a href/blog/2015/09/30/the-adjunction-that-induces-the-reader-monad/>An Adjunction That Induces the Reader Monad/a> /li> li classpost> a href/blog/2015/06/23/a-scala-comonad-tutorial/>A Scala Comonad Tutorial, Part 1/a> /li> /ul>/section>section> h1>GitHub Repos/h1> ul idgh_repos> li classloading>Status updating…/li> /ul> a hrefhttps://github.com/runarorama>@runarorama/a> on GitHub script typetext/javascript> $(document).ready(function(){ if (!window.jXHR){ var jxhr document.createElement(script); jxhr.type text/javascript; jxhr.src /javascripts/libs/jXHR.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(jxhr, s); } github.showRepos({ user: runarorama, count: 4, skip_forks: false, target: #gh_repos }); }); /script> script src/javascripts/github.js typetext/javascript> /script>/section> /aside> /div> /div> footer rolecontentinfo>p> Copyright © 2018 - Rúnar Bjarnason - span classcredit>Powered by a hrefhttp://octopress.org>Octopress/a>/span>/p>/footer> div idfb-root>/div>script>(function(d, s, id) { var js, fjs d.getElementsByTagName(s)0; if (d.getElementById(id)) {return;} js d.createElement(s); js.id id; js.async true; js.src //connect.facebook.net/en_US/all.js#appId212934732101925&xfbml1; fjs.parentNode.insertBefore(js, fjs);}(document, script, facebook-jssdk));/script> script typetext/javascript> (function() { var script document.createElement(script); script.type text/javascript; script.async true; script.src https://apis.google.com/js/plusone.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(script, s); })(); /script> script typetext/javascript> (function(){ var twitterWidgets document.createElement(script); twitterWidgets.type text/javascript; twitterWidgets.async true; twitterWidgets.src //platform.twitter.com/widgets.js; document.getElementsByTagName(head)0.appendChild(twitterWidgets); })(); /script>/body>/html>
Port 443
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 234353Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Thu, 20 Sep 2018 02:42:15 GMTAccess-Control-Allow-Origin: *ETag: 5ba30907-39371expires: Mon, 21 Oct 2024 14:09:52 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: F37D:10EB:700D49:733447:67165E58Accept-Ranges: bytesAge: 0Date: Mon, 21 Oct 2024 13:59:52 GMTVia: 1.1 varnishX-Served-By: cache-bfi-kbfi7400090-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1729519192.188786,VS0,VE94Vary: Accept-EncodingX-Fastly-Request-ID: 72de1dd154283afc4422ef1fea63d2dc3403202f !DOCTYPE html>!--if IEMobile 7 >html classno-js iem7>!endif-->!--if lt IE 9>html classno-js lte-ie8>!endif-->!--if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)>!-->html classno-js langen>!--!endif-->head> meta charsetutf-8> title>Higher Order/title> meta nameauthor contentRúnar Bjarnason> meta namedescription contentI want to talk about a comonad that came up at work the other day. Actually, two of them, as the data structure in question is a comonad in at least …> !-- http://t.co/dKP3o1e --> meta nameHandheldFriendly contentTrue> meta nameMobileOptimized content320> meta nameviewport contentwidthdevice-width, initial-scale1> link relcanonical hrefhttp://runarorama.github.com/> link href/favicon.png relicon> link href/stylesheets/screen.css mediascreen, projection relstylesheet typetext/css> link href/atom.xml relalternate titleHigher Order typeapplication/atom+xml> script src/javascripts/modernizr-2.0.js>/script> script src//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js>/script> script>!window.jQuery && document.write(unescape(%3Cscript src/javascripts/libs/jquery.min.js%3E%3C/script%3E))/script> script src/javascripts/octopress.js typetext/javascript>/script> !--Fonts from Googles Web font directory at http://google.com/webfonts -->link hrefhttp://fonts.googleapis.com/css?familyPT+Serif:regular,italic,bold,bolditalic relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyPT+Sans:regular,italic,bold,bolditalic relstylesheet typetext/css>script typetext/javascript src//use.typekit.net/fbs7fzv.js>/script>script typetext/javascript>try{Typekit.load();}catch(e){}/script> script typetext/javascript> var _gaq _gaq || ; _gaq.push(_setAccount, UA-34544663-1); _gaq.push(_trackPageview); (function() { var ga document.createElement(script); ga.type text/javascript; ga.async true; ga.src (https: document.location.protocol ? https://ssl : http://www) + .google-analytics.com/ga.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s); })(); /script> link href/stylesheets/datatable.css mediascreen, projection relstylesheet typetext/css />/head>body > header rolebanner>hgroup> h1>a href/>Higher Order/a>/h1> h2>Philosophy and functional programming./h2> /hgroup>/header> nav rolenavigation>ul classsubscription data-subscriptionrss> li>a href/atom.xml relsubscribe-rss titlesubscribe via RSS>RSS/a>/li> /ul> form actionhttp://google.com/search methodget> fieldset rolesearch> input typehidden namesitesearch valuerunarorama.github.com> input classsearch typetext nameq results0 placeholderSearch/> /fieldset>/form> ul classmain-navigation> li>a href/>Blog/a>/li> li>a href/blog/archives>Archives/a>/li> li>a href/about>About/a>/li>/ul>/nav> div idmain> div idcontent> div classblog-index> article> header> h1 classentry-title>a href/blog/2016/04/02/a-comonad-of-graph-decompositions/>A Comonad of Graph Decompositions/a>/h1> p classmeta> time classentry-date datetime2016-04-02T13:02:54-04:00>span classdate>span classdate-month>Apr/span> span classdate-day>2/span>span classdate-suffix>nd/span>, span classdate-year>2016/span>/span> span classtime>1:02 pm/span>/time> /p> /header> div classentry-content>p>I want to talk about a comonad that came up at a hrefhttp://innovation.verizon.com/>work/a> the other day. Actually, two of them, as the data structure in question is a comonad in at least two ways, and the issue that came up is related to the difference between those two comonads./p>p>This post is sort of a continuation of the a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>Comonad Tutorial/a>, and we can call this “part 3”. I’m going to assume the reader has a basic familiarity with comonads./p>h2>Inductive Graphs/h2>p>At a hrefhttp://innovation.verizon.com/>work/a>, we develop and use a Scala library called a hrefhttp://github.com/oncue/quiver>Quiver/a> for working with a hrefhttps://en.wikipedia.org/wiki/Graph_(discrete_mathematics>graphs/a>). In this library, a graph is a recursively defined immutable data structure. A graph, with node IDs of type code>V/code>, node labels code>N/code>, and edge labels code>E/code>, is constructed in one of two ways. It can be empty:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>empty/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Or it can be of the form code>c & g/code>, where code>c/code> is the em>context/em> of one node of the graph and code>g/code> is the rest of the graph with that node removed:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>/span>span classline> span classn>inEdges/span>span classk>:/span> span classkt>Vector/span>span classo>(/span>span classkt>E/span>,span classkt>V/span>span classo>),/span>/span>span classline> span classn>vertex/span>span classk>:/span> span classkt>V/span>span classo>,/span>/span>span classline> span classn>label/span>span classk>:/span> span classkt>N/span>span classo>,/span>/span>span classline> span classn>outEdges/span>span classk>:/span> span classkt>Vector/span>span classo>(/span>span classkt>E/span>,span classkt>V/span>span classo>)/span>/span>span classline>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classo>&(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span> span classk>/span> span classo>???/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>By the same token, we can decompose a graph on a particular node:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>span classline>span classn>v/span>span classk>:/span> span classkt>V/span>/span>span classline>/span>span classline>span classn>g/span> span classn>decomp/span> span classn>v/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Where a code>GDecomp/code> is a code>Context/code> for the node code>v/code> (if it exists in the graph) together with the rest of the graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>ctx/span>span classk>:/span> span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>,/span> span classn>rest/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Recursive decomposition/h2>p>Let’s say we start with a graph code>g/code>, like this:/p>p>img src/images/quiver/Quiver1.png width300 altExample graph />/p>p>I’m using an em>undirected/em> graph here for simplification. An undirected graph is one in which the edges don’t have a direction. In Quiver, this is represented as a graph where the “in” edges of each node are the same as its “out” edges./p>p>If we decompose on the node code>a/code>, we get a view of the graph from the perspective of code>a/code>. That is, we’ll have a code>Context/code> letting us look at the label, vertex ID, and edges to and from code>a/code>, and we’ll also have the remainder of the graph, with the node code>a/code> “broken off”:/p>p>img src/images/quiver/decompa.png width400 altGDecomp on a />/p>p>Quiver can arbitrarily choose a node for us, so we can look at the context of some “first” node:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>span classline>/span>span classline>span classn>g/span>span classo>./span>span classn>decompAny/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>We can keep decomposing the remainder recursively, to perform an arbitrary calculation over the entire graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>f/span>span classk>:/span> span classo>(/span>span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>,/span> span classn>B/span>span classo>)/span> span classk>>/span> span classn>B/span>/span>span classline>span classn>b/span>span classk>:/span> span classkt>B/span>/span>span classline>/span>span classline>span classo>(/span>span classn>g/span> span classn>fold/span> span classn>b/span>span classo>)(/span>span classn>f/span>span classo>)/span>span classk>:/span> span classkt>B/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The implementation of code>fold/code> will be something like:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>g/span>span classo>./span>span classn>decompAny/span> span classn>map/span> span classo>{/span>/span>span classline> span classk>case/span> span classnc>GDecomp/span>span classo>(/span>span classn>ctx/span>span classo>,/span> span classn>rest/span>span classo>)/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>ctx/span>span classo>,/span> span classn>rest/span>span classo>./span>span classn>fold/span>span classo>(/span>span classn>b/span>span classo>)(/span>span classn>f/span>span classo>))/span>/span>span classline>span classo>}/span> span classn>getOrElse/span> span classn>b/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>For instance, if we wanted to count the edges in the graph code>g/code>, we could do:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classo>(/span>span classn>g/span> span classn>fold/span> span classmi>0/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classn>b/span>span classo>)/span> span classk>>/span> span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>b/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The recursive decomposition will guarantee that our function doesn’t see any given edge more than once. For the graph code>g/code> above, code>(g fold b)(f)/code> would look something like this:/p>p>img src/images/quiver/fold.png altGraph fold />/p>h2>Graph Rotations/h2>p>Let’s now say that we wanted to find the maximum a hrefhttps://en.wikipedia.org/wiki/Degree_(graph_theory>degree/a> of a graph. That is, find the highest number of edges to or from any node./p>p>A first stab might be:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classo>(/span>span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span>span classo>)/span> span classn>max/span> span classn>z/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But that would get the incorrect result. In our graph code>g/code> above, the nodes code>b/code>, code>d/code>, and code>f/code> have a degree of 3, but this fold would find the highest degree to be 2. The reason is that once our function gets to look at code>b/code>, its edge to code>a/code> has already been removed, and once it sees code>f/code>, it has no edges left to look at./p>p>This was the issue that came up at work. This behaviour of code>fold/code> is both correct and useful, but it can be surprising. What we might expect is that instead of receiving successive decompositions, our function sees “all rotations” of the graph through the code>decomp/code> operator:/p>p>img src/images/quiver/rotations.png altAll rotations />/p>p>That is, we often want to consider each node in the context of the entire graph we started with. In order to express that with code>fold/code>, we have to decompose the original graph at each step:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decompose/span>span classo>(/span>span classn>c/span>span classo>./span>span classn>vertex/span>span classo>)./span>span classn>map/span> span classo>{/span>/span>span classline> span classk>case/span> span classnc>GDecomp/span>span classo>(/span>span classnc>Context/span>span classo>(/span>span classn>ins/span>span classo>,/span> span classk>_/span>span classo>,/span> span classk>_/span>span classo>,/span> span classn>outs/span>span classo>),/span> span classk>_/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>outs/span>span classo>./span>span classn>size/span>/span>span classline> span classo>}./span>span classn>getOrElse/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classn>max/span> span classn>z/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But what if we could have a combinator that em>labels each node with its context/em>?/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>contextGraph/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Context/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>/span>,span classkt>E/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visually, that looks something like this:/p>p>img src/images/quiver/duplicate.png altAll contexts />/p>p>If we now fold over code>contextGraph(g)/code> rather than code>g/code>, we get to see the whole graph from the perspective of each node in turn. We can then write the code>maxDegree/code> function like this:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>maxDegree/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>N/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span>/span>span classline> span classn>contextGraph/span>span classo>(/span>span classn>g/span>span classo>)./span>span classn>fold/span>span classo>(/span>span classmi>0/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>z/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>z/span> span classn>max/span> span classo>(/span>span classn>c/span>span classo>./span>span classn>label/span>span classo>./span>span classn>ins/span>span classo>./span>span classn>size/span> span classo>+/span> span classn>c/span>span classo>./span>span classn>label/span>span classo>./span>span classn>outs/span>span classo>./span>span classn>size/span>span classo>)/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Two different comonads/h2>p>This all sounds suspiciously like a comonad! Of course, code>Graph/code> itself is not a comonad, but code>GDecomp/code> definitely is. The code>counit/code> just gets the label of the node that’s been code>decomp/code>ed out:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>gdecompComonad/span>span classo>/span>span classkt>V/span>,span classkt>E/span>span classo>/span> span classk>/span> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>α/span>,span classkt>E/span>span classo>/span> span classo>{/span>/span>span classline>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>label/span>/span>span classline>/span>span classline> span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classo>???/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>cobind/code> can be implemented in one of two ways. There’s the “successive decompositions” version:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classnc>GDecomp/span>span classo>(/span>span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>g/span>span classo>)),/span>/span>span classline> span classn>g/span>span classo>./span>span classn>rest/span>span classo>./span>span classn>decompAny/span>span classo>./span>span classn>map/span> span classo>{/span>/span>span classline> span classk>val/span> span classnc>GDecomp/span>span classo>(/span>span classn>c/span>span classo>,/span> span classn>r/span>span classo>)/span> span classk>/span> span classn>cobind/span>span classo>(/span>span classk>_/span>span classo>)(/span>span classn>f/span>span classo>)/span>/span>span classline> span classn>c/span> span classo>&/span> span classn>r/span>/span>span classline> span classo>}/span> span classn>getOrElse/span> span classn>empty/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visually, it looks like this:/p>p>img src/images/quiver/extend.png altExtend over successive decompositions />/p>p>It em>exposes the substructure/em> of the graph by storing it in the labels of the nodes. It’s very much like the familiar code>NonEmptyList/code> comonad, which replaces each element in the list with the whole sublist from that element on./p>p>So this is the comonad of em>recursive folds over a graph/em>. Really its action is the same as as just code>fold/code>. It takes a computation on one decomposition of the graph, and extends it to all sub-decompositions./p>p>But there’s another, comonad that’s much more useful em>as a comonad/em>. That’s the comonad that works like code>contextGraph/code> from before, except instead of copying the context of a node into its label, we copy the whole decomposition; both the context and the remainder of the graph./p>p>That one looks visually more like this:/p>p>img src/images/quiver/redecorate.png altExtend over all rotations />/p>p>Its code>cobind/code> takes a computation focused on one node of the graph (that is, on a code>GDecomp/code>), repeats that for every other decomposition of the original graph in turn, and stores the results in the respective node labels:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>cobind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>)(/span>/span>span classline> span classn>f/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>V/span>,span classkt>A/span>,span classkt>E/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>GDecomp/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classk>val/span> span classn>orig/span> span classk>/span> span classn>g/span>span classo>./span>span classn>ctx/span> span classo>&/span> span classn>g/span>span classo>./span>span classn>rest/span>/span>span classline> span classnc>GDecomp/span>span classo>(/span>span classn>g/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>g/span>span classo>)),/span>/span>span classline> span classn>rest/span>span classo>./span>span classn>fold/span>span classo>(/span>span classn>empty/span>span classo>)/span> span classo>{/span> span classo>(/span>span classn>c/span>span classo>,/span> span classn>acc/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>c/span>span classo>./span>span classn>copy/span>span classo>(/span>span classn>label/span> span classk>/span> span classn>f/span>span classo>(/span>span classn>orig/span>span classo>./span>span classn>decomp/span>span classo>(/span>span classn>c/span>span classo>./span>span classn>vertex/span>span classo>)./span>span classn>get/span>span classo>))/span> span classo>&/span> span classn>acc/span>/span>span classline> span classo>})/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This is useful for algorithms where we want to label every node with some information computed from its neighborhood. For example, some clustering algorithms start by assigning each node its own cluster, then repeatedly joining nodes to the most popular cluster in their immediate neighborhood, until a fixed point is reached./p>p>As a simpler example, we could take the average value for the labels of neighboring nodes, to apply something like a low-pass filter to the whole graph:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>lopass/span>span classo>/span>span classkt>V/span>,span classkt>E/span>span classo>(/span>span classn>g/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Int/span>,span classkt>E/span>span classo>)/span>span classk>:/span> span classkt>Graph/span>span classo>/span>span classkt>V/span>,span classkt>Int/span>,span classkt>E/span>span classo>/span> span classk>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decompAny/span>span classo>./span>span classn>map/span> span classo>{/span> span classn>d/span> span classk>>/span> span classn>cobind/span>span classo>(/span>span classn>d/span>span classo>)/span> span classo>{/span> span classn>x/span> span classk>>/span>/span>span classline> span classk>val/span> span classn>neighbors/span> span classk>/span> span classo>(/span>span classn>x/span>span classo>./span>span classn>inEdges/span> span classo>++/span> span classn>x/span>span classo>./span>span classn>outEdges/span>span classo>)./span>span classn>map/span> span classo>{/span> span classn>n/span> span classk>>/span>/span>span classline> span classn>g/span>span classo>./span>span classn>decomp/span>span classo>(/span>span classn>n/span>span classo>)./span>span classn>get/span>span classo>./span>span classn>ctx/span>span classo>./span>span classn>label/span>/span>span classline> span classo>}/span>/span>span classline> span classo>(/span>span classn>neighbors/span>span classo>./span>span classn>sum/span> span classo>+/span> span classn>x/span>span classo>./span>span classn>label/span>span classo>)/span> span classo>//span> span classo>(/span>span classn>neighbors/span>span classo>./span>span classn>length/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classo>}}/span> span classn>getOrElse/span> span classn>g/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The difference between these two comonad instances is essentially the same as the difference between a hrefhttps://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/NonEmptyList.scala>code>NonEmptyList/code>/a> and the nonempty list a hrefhttps://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Zipper.scala>code>Zipper/code>/a>./p>p>It’s this latter “decomp zipper” comonad that I decided to ultimately include as the code>Comonad/code> instance for code>quiver.GDecomp/code>./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/10/12/freedom-and-forgetfulness/>Freedom and Forgetfulness/a>/h1> p classmeta> time classentry-date datetime2015-10-12T23:13:54-04:00>span classdate>span classdate-month>Oct/span> span classdate-day>12/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:13 pm/span>/time> /p> /header> div classentry-content>p>I’ve been having fun exploring adjunctions lately and thinking about how we can take a monad apart and compose it the other way to get a comonad, and vice versa. Often I’ll find that a comonad counterpart of a given monad gives an interesting perspective on that monad, and ditto for a monad cousin to a given comonad./p>h2>The monad for monoids/h2>p>Let’s take an example. There is a category of monoids em>Mon/em> with monoids as objects and monoid homomorphisms as arrows between them. Then there is a functor from em>Set/em> to em>Mon/em> that takes any ordinary type code>A/code> to the em>free monoid/em> generated by code>A/code>. This is just the code>ListA/code> type together with concatenation as the multiplication and the empty list as the identity element./p>p>This free functor has a right adjoint that takes any monoid code>M/code> in em>Mon/em> to its em>underlying set/em> code>M/code>. That is, this right adjoint “forgets” that code>M/code> is a monoid, leaving us with just an ordinary type./p>p>If we compose these two functors, we get a monad. If we start with a type code>A/code>, get its free monoid (the code>ListA/code> monoid), and then go from there to the underlying type of the free monoid, we end up with the type code>ListA/code>. The code>unit/code> of our adjunction is then a function from any given type code>A/code> to the type code>ListA/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>List/span>span classo>(/span>span classn>a/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h3>Structure ⊣ Interpretation/h3>p>But then what is the code>counit/code>? Remember that for any adjunction, we can compose the functors one way to get a monad, and compose them the other way to get a comonad./p>p>In that case we have to start with a monoid code>M/code>, then “forget”, giving us the plain type code>M/code>. Then we take the free monoid of that to end up with the code>ListM/code> monoid./p>p>But notice that we are now in the monoid category. In that category, code>List/code> is a comonad. And since we’re in the category of monoids, the code>counit/code> has to be a em>monoid homomorphism/em>. It goes from the free monoid code>ListA/code> to the monoid code>A/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A:Monoid/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>foldRight/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>A/span>span classo>./span>span classn>zero/span>span classo>)(/span>span classnc>Monoid/span>span classo>/span>span classkt>A/span>span classo>./span>span classn>append/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>If we apply the code>counit/code> for this comonad to the free monoid, we get the code>join/code> for our monad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classn>counit/span>span classo>(/span>span classn>as/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And to get the code>duplicate/code> or code>extend/code> operation in the comonad, we just turn the crank on the adjunction:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classk>_/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>duplicate/code> just puts each element into its own sublist. With regard to code>extend/code>, this just means that given any catamorphism on code>List/code>, we can turn that into a homomorphism on free monoids./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>as/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>as/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>x/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classn>x/span>span classo>)))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>All the interesting parts of code>List/code> are the parts that make it a monoid, and our comonad here is already in a category full of monoids. Therefore the coKleisli composition in this comonad is kind of uninteresting. All it’s saying is that if we can fold a code>ListA/code> to a code>B/code>, and a code>ListB/code> to a code>C/code>, then we can fold a code>ListA/code> to a code>C/code>, by considering each element as a singleton list./p>h2>Forget ⊣ Cofree/h2>p>Let’s now consider another category, call it em>End(Set)/em>, which is the em>category of endofunctors/em> in em>Set/em>./p>p>The arrows in this category are natural transformations:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>~>/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>apply/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>There’s another category, em>Com/em>, which is the em>category of comonads/em> on em>Set/em>. The arrows here are em>comonad homomorphisms/em>. A comonad homomorphism from code>F/code> to code>G/code> is a natural transformation code>f: F ~> G/code> satisfying the homomorphism law:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>f/span>span classo>(/span>span classn>x/span>span classo>)./span>span classn>duplicate/span> span classo>/span> span classn>f/span>span classo>(/span>span classn>x/span>span classo>./span>span classn>duplicate/span>span classo>)/span> span classn>map/span> span classn>f/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>There is a forgetful functor code>Forget: Com -> End(Set)/code> that takes a comonad to its underlying endofunctor (forgetting that it’s a comonad). And this functor has a em>right/em> adjoint code>Cofree: End(Set) -> Com/code> which generates a cofree comonad on a given endofunctor code>F/code>. This is the following data type:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cofree/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that not only is the endofunctor code>CofreeF,?/code> a comonad (in em>Set/em>) for any functor code>F/code>, but the higher-order type constructor code>Cofree/code> is itself is a comonad in the endofunctor category. It’s this latter comonad that is induced by the code>Forget ⊣ Cofree/code> adjunction. That is, we start at an endofunctor code>F/code>, then go to comonads via code>CofreeF,?/code>, then back to endofunctors via code>Forget/code>./p>p>The code>unit/code> for this adjunction is then a comonad homomorphism. Remember, this is the code>unit/code> for a monad in the category em>Com/em> of comonads:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Comonad/span>,span classkt>A/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cofree/span>span classo>(/span>span classn>x/span>span classo>./span>span classn>counit/span>span classo>,/span> span classn>x/span>span classo>./span>span classn>extend/span>span classo>(/span>span classn>unit/span>span classo>(/span>span classk>_/span>span classo>)))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This will start with a value of type code>FA/code> in the comonad code>F/code>, and then em>unfold/em> an code>F/code>-branching stream from it. Note that the first level of this will have the same structure as code>x/code>./p>p>If we take code>unit/code> across to the em>End(Set)/em> category, we get the code>duplicate/code> for our comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>?/span>span classo>/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>unit/span>span classo>(/span>span classn>c/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that this is em>not/em> the code>duplicate/code> for the code>CofreeF,?/code> comonad. It’s the duplicate for code>Cofree/code> itself which is a comonad in an endofunctor category./p>p>Turning the crank on the adjunction, the code>counit/code> for this comonad now has to be the inverse of our code>unit/code>. It takes the heads of all the branches of the given code>F/code>-branching stream./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Functor/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>c/span>span classo>./span>span classn>tail/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>head/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Sending that over to the comonad category, we get the code>join/code> for our monad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>span classkt>:Comonad/span>,span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>?/span>span classo>/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>counit/span>span classo>(/span>span classn>c/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>/div> /article> article> header> h1 classentry-title>a href/blog/2015/10/04/scala-comonad-tutorial-part-2/>Scala Comonad Tutorial, Part 2/a>/h1> p classmeta> time classentry-date datetime2015-10-04T17:36:31-04:00>span classdate>span classdate-month>Oct/span> span classdate-day>4/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>5:36 pm/span>/time> /p> /header> div classentry-content>p>In the a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>previous post/a>, we looked at the Reader/Writer monads and comonads, and discussed in general what comonads are and how they relate to monads. This time around, we’re going to look at some more comonads, delve briefly into adjunctions, and try to get some further insight into what it all means./p>h2>Nonempty structures/h2>p>Since a comonad has to have a code>counit/code>, it must be “pointed” or nonempty in some sense. That is, given a value of type code>WA/code> for some comonad code>W/code>, we must be able to get a value of type code>A/code> out./p>p>The identity comonad is a simple example of this. We can always get a value of type code>A/code> out of code>IdA/code>. A slightly more interesting example is that of non-empty lists:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>NEL/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>So a nonempty list is a value of type code>A/code> together with either another list or code>None/code> to mark that the list has terminated. Unlike the traditional code>List/code> data structure, we can always safely get the code>head/code>./p>p>But what is the comonadic code>duplicate/code> operation here? That should allow us to go from code>NELA/code> to code>NELNELA/code> in such a way that the comonad laws hold. For nonempty lists, an implementation that satisfies those laws turns out to be:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>NEL/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>head/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>tail/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classo>.../span>/span>span classline> span classk>def/span> span classn>tails/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>NEL/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>tail/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>tails/span>span classo>))/span>/span>span classline> span classo>.../span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The code>tails/code> operation returns a list of all the suffixes of the given list. This list of lists is always nonempty, because the first suffix is the list itself. For example, if we have the nonempty list code>1,2,3/code> (to use a more succinct notation), the code>tails/code> of that will be code>1,2,3, 2,3, 3/code>/p>p>To get an idea of what this em>means/em> in the context of a comonadic program, think of this in terms of coKleisli composition, or code>extend/code> in the comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>NEL/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>tails/span> span classn>map/span> span classn>f/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>When we code>map/code> over code>tails/code>, the function code>f/code> is going to receive each suffix of the list in turn. We apply code>f/code> to each of those suffixes and collect the results in a (nonempty) list. So code>1,2,3.extend(f)/code> will be code>f(1,2,3), f(2,3), f(3)/code>./p>p>The name code>extend/code> refers to the fact that it takes a “local” computation (here a computation that operates on a list) and extends that to a “global” computation (here over all suffixes of the list)./p>p>Or consider this class of nonempty trees (often called Rose Trees):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Tree/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>tip/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>sub/span>span classk>:/span> span classkt>List/span>span classo>/span>span classkt>Tree/span>span classo>/span>span classkt>A/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>A tree of this sort has a value of type code>A/code> at the tip, and a (possibly empty) list of subtrees underneath. One obvious use case is something like a directory structure, where each code>tip/code> is a directory and the corresponding code>sub/code> is its subdirectories./p>p>This is also a comonad. The code>counit/code> is obvious, we just get the code>tip/code>. And here’s a code>duplicate/code> for this structure:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Tree/span>span classo>/span>span classkt>Tree/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Tree/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>sub/span>span classo>./span>span classn>map/span>span classo>(/span>span classk>_/span>span classo>./span>span classn>duplicate/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now, this obviously gives us a tree of trees, but what is the structure of that tree? It will be em>a tree of all the subtrees/em>. The code>tip/code> will be code>this/code> tree, and the code>tip/code> of each proper subtree under it will be the entire subtree at the corresponding point in the original tree./p>p>That is, when we say code>t.duplicate.map(f)/code> (or equivalently code>t extend f/code>), our code>f/code> will receive each subtree of code>t/code> in turn and perform some calculation over that entire subtree. The result of the whole expression code>t extend f/code> will be a tree mirroring the structure of code>t/code>, except each node will contain code>f/code> applied to the corresponding subtree of code>t/code>./p>p>To carry on with our directory example, we can imagine wanting a detailed space usage summary of a directory structure, with the size of the whole tree at the code>tip/code> and the size of each subdirectory underneath as tips of the subtrees, and so on. Then code>d extend size/code> creates the tree of sizes of recursive subdirectories of code>d/code>./p>h2>The cofree comonad/h2>p>You may have noticed that the implementations of code>duplicate/code> for rose trees and code>tails/code> for nonempty lists were basically identical. The only difference is that one is mapping over a code>List/code> and the other is mapping over an code>Option/code>. We can actually abstract that out and get a comonad for any functor code>F/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cofree/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>counit/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>sub/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>(/span>span classk>implicit/span> span classn>F/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>F/span>span classo>)/span>span classk>:/span> span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>Cofree/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cofree/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>F/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>sub/span>span classo>)(/span>span classk>_/span>span classo>./span>span classn>duplicate/span>span classo>))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>A really common kind of structure is something like the type code>CofreeMapK,?,A/code> of trees where the code>counit/code> is some kind of summary and each key of type code>K/code> in the code>Map/code> of subtrees corresponds to some drilldown for more detail. This kind of thing appears in portfolio management applications, for example./p>p>Compare this structure with the em>free monad/em>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>sealed/span> span classk>trait/span> span classnc>Free/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>/span>/span>span classline>span classnc>case/span> span classk>class/span> span classnc>Return/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classk>extends/span> span classnc>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span>/span>span classline>span classk>case/span> span classk>class/span> span classnc>Suspend/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>A/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>)/span> span classk>extends/span> span classnc>Free/span>span classo>/span>span classkt>F/span>,span classkt>A/span>span classo>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>While the free monad is em>either/em> an code>A/code> or a recursive step suspended in an code>F/code>, the cofree comonad is em>both/em> an code>A/code> em>and/em> a recursive step suspended in an code>F/code>. They really are duals of each other in the sense that the monad is a coproduct and the comonad is a product./p>h2>Comparing comonads to monads (again)/h2>p>Given this difference, we can make some statements about what it means:/p>ul>li>code>FreeF,A/code> is a type of “leafy tree” that branches according to code>F/code>, with values of type code>A/code> at the leaves, while code>CofreeF,A/code> is a type of “node-valued tree” that branches according to code>F/code> with values of type code>A/code> at the nodes./li>li>If code>Exp/code> defines the structure of some expression language, then code>FreeExp,A/code> is the type of abstract syntax trees for that language, with free variables of type code>A/code>, and monadic code>bind/code> literally binds expressions to those variables. Dually, code>CofreeExp,A/code> is the type of em>closed/em> exresspions whose subexpressions are annotated with values of type code>A/code>, and comonadic code>extend/code> em>reannotates/em> the tree. For example, if you have a type inferencer code>infer/code>, then code>e extend infer/code> will annotate each subexpression of code>e/code> with its inferred type./li>/ul>p>This comparison of code>Free/code> and code>Cofree/code> actually says something about monads and comonads in general:/p>ul>li>All monads can model some kind of leafy tree structure, and all comonads can be modeled by some kind of node-valued tree structure./li>li>In a monad code>M/code>, if code>f: A > MB/code>, then code>xs map f/code> allows us to take the values at the leaves (code>a:A/code>) of a monadic structure code>xs/code> and em>substitute/em> an entire structure (code>f(a)/code>) for each value. A subsequent code>join/code> then renormalizes the structure, eliminating the “seams” around our newly added substructures. In a em>comonad/em> code>W/code>, code>xs.duplicate/code> denormalizes, or exposes the substructure of code>xs:WA/code> to yield code>WWA/code>. Then we can map a function code>f: WA > B/code> over that to get a code>B/code> for each part of the substructure and em>redecorate/em> the original structure with those values. (See Uustalu and Vene’s excellent paper a hrefhttp://cs.ioc.ee/~tarmo/papers/sfp01-book.pdf>The Dual of Substitution is Redecoration/a> for more on this connection.)/li>li>A monad defines a class of programs whose subexpressions are incrementally generated from the outputs of previous expressions. A comonad defines a class of programs that incrementally generate output from the substructure of previous expressions./li>li>A monad adds structure by consuming values. A comonad adds values by consuming structure./li>/ul>h2>The relationship between Reader and Coreader/h2>p>If we look at a Kleisli arrow in the code>ReaderR,?/code> comonad, it looks like code>A > ReaderR,B/code>, or expanded out: code>A > R > B/code>. If we uncurry that, we get code>(A, R) > B/code>, and we can go back to the original by currying again. But notice that a value of type code>(A, R) > B/code> is a coKleisli arrow in the code>Coreader/code> comonad! Remember that code>CoreaderR,A/code> is really a pair code>(A, R)/code>./p>p>So the answer to the question of how code>Reader/code> and code>Coreader/code> are related is that there is a one-to-one correspondence between a Kleisli arrow in the code>Reader/code> monad and a coKleisli arrow in the code>Coreader/code> comonad. More precisely, the Kleisli category for code>ReaderR,?/code> is isomorphic to the coKleisli category for code>CoreaderR,?/code>. This isomorphism is witnessed by currying and uncurrying./p>p>In general, if we have an isomorphism between arrows like this, we have what’s called an em>adjunction/em>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Adjunction/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>left/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>B/span>span classo>/span>/span>span classline> span classk>def/span> span classn>right/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>In an code>AdjunctionF,G/code>, we say that code>F/code> is em>left adjoint/em> to code>G/code>, often expressed with the notation code>F ⊣ G/code>./p>p>We can clearly make an code>Adjunction/code> for code>CoreaderR,?/code> and code>ReaderR,?/code> by using code>curry/code> and code>uncurry/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>homSetAdj/span>span classo>/span>span classkt>R/span>span classo>/span> span classk>/span> span classk>new/span> span classnc>Adjunction/span>span classo>(/span>span classkt>?/span>, span classkt>R/span>span classo>)/span>, span classkt>R/span> span classk>>/span> span classkt>?/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>left/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classo>((/span>span classkt>A/span>span classo>,/span> span classkt>R/span>span classo>))/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>R/span> span classk>>/span> span classn>B/span> span classk>/span>/span>span classline> span classnc>Function/span>span classo>./span>span classn>untupled/span>span classo>(/span>span classn>f/span>span classo>)./span>span classn>curried/span>/span>span classline> span classk>def/span> span classn>right/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>R/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classo>((/span>span classkt>A/span>span classo>,/span> span classkt>R/span>span classo>))/span> span classk>>/span> span classn>B/span> span classk>/span>/span>span classline> span classnc>Function/span>span classo>./span>span classn>uncurried/span>span classo>(/span>span classn>f/span>span classo>)./span>span classn>tupled/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The additional code>tupled/code> and code>untupled/code> come from the unfortunate fact that I’ve chosen Scala notation here and Scala differentiates between functions of two arguments and functions of one argument that happens to be a pair./p>p>So a more succinct description of this relationship is that code>Coreader/code> is left adjoint to code>Reader/code>./p>p>Generally the left adjoint functor em>adds/em> structure, or is some kind of “producer”, while the right adjoint functor em>removes/em> (or “forgets”) structure, or is some kind of “consumer”./p>h2>Composing adjoint functors/h2>p>An interesting thing about adjunctions is that if you have an adjoint pair of functors code>F ⊣ G/code>, then code>FG?/code> always forms a comonad, and code>GF?/code> always forms a monad, in a completely canonical and amazing way:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>monad/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>(/span>span classn>A/span>span classk>:/span> span classkt>Adjunction/span>span classo>/span>span classkt>F/span>,span classkt>G/span>span classo>)(/span>span classk>implicit/span> span classn>G/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>G/span>span classo>)/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Monad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>α/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classo>>/span> span classn>A/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>A/span>span classo>./span>span classn>left/span>span classo>(/span>span classn>identity/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>a/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>bind/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>B/span>span classo>)/span>span classk>:/span> span classkt>G/span>span classo>/span>span classkt>F/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>G/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>a/span>span classo>)(/span>span classn>A/span>span classo>./span>span classn>right/span>span classo>(/span>span classn>f/span>span classo>))/span>/span>span classline> span classo>}/span>/span>span classline>/span>span classline>span classk>def/span> span classn>comonad/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span>,span classkt>G/span>span classo>/span>span classk>_/span>span classo>(/span>span classn>A/span>span classk>:/span> span classkt>Adjunction/span>span classo>/span>span classkt>F/span>,span classkt>G/span>span classo>)(/span>span classk>implicit/span> span classn>F/span>span classk>:/span> span classkt>Functor/span>span classo>/span>span classkt>F/span>span classo>)/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>λ/span>span classo>/span>span classkt>α/span> span classk>>/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>α/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>A/span>span classo>./span>span classn>right/span>span classo>(/span>span classn>identity/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>a/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>G/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>F/span>span classo>./span>span classn>map/span>span classo>(/span>span classn>a/span>span classo>)(/span>span classn>A/span>span classo>./span>span classn>left/span>span classo>(/span>span classn>f/span>span classo>))/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that this says something about monads and comonads. Since the left adjoint code>F/code> is a producer and the right adjoint code>G/code> is a consumer, a monad always consumes and then produces, while a comonad always produces and then consumes./p>p>Now, if we compose code>Reader/code> and code>Coreader/code>, which monad do we get?/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>scala/span>span classo>>/span> span classk>def/span> span classn>M/span>span classo>/span>span classkt>S/span>span classo>/span> span classk>/span> span classn>monad/span>span classo>(/span>span classn>homSetAdj/span>span classo>/span>span classkt>S/span>span classo>)/span>/span>span classline>span classn>M/span>span classk>:/span> span classerr>/span>span classkt>S/span>span classerr>/span>span classo>>/span> span classn>scalaz/span>span classo>./span>span classnc>Monad/span>span classo>/span>span classkt>α/span>span classo>/span>span classkt>S/span> span classk>>/span> span classo>(/span>span classkt>α/span>, span classkt>S/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>That’s the code>StateS,?/code> monad!/p>p>Now if we compose it the other way, we should get a comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classn>scala/span>span classo>>/span> span classk>def/span> span classn>W/span>span classo>/span>span classkt>S/span>span classo>/span> span classk>/span> span classn>comonad/span>span classo>(/span>span classn>homSetAdj/span>span classo>/span>span classkt>S/span>span classo>)/span>/span>span classline>span classn>W/span>span classk>:/span> span classerr>/span>span classkt>S/span>span classerr>/span>span classo>>/span> span classn>scalaz/span>span classo>./span>span classnc>Comonad/span>span classo>/span>span classkt>α/span>span classo>(/span>span classkt>S/span> span classk>>/span> span classkt>α/span>, span classkt>S/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>What is that? It’s the code>StoreS,?/code> comonad:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>peek/span>span classk>:/span> span classkt>S/span> span classo>>/span> span classn>A/span>span classo>,/span> span classn>cursor/span>span classk>:/span> span classkt>S/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>extract/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>peek/span>span classo>(/span>span classn>cursor/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>, span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Store/span>span classo>(/span>span classn>s/span> span classk>>/span> span classn>f/span>span classo>(/span>span classnc>Store/span>span classo>(/span>span classn>peek/span>span classo>,/span> span classn>s/span>span classo>)),/span> span classn>cursor/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>, span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classn>extend/span>span classo>(/span>span classn>identity/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Store/span>span classo>/span>span classkt>S/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>extend/span>span classo>(/span>span classn>s/span> span classk>>/span> span classn>f/span>span classo>(/span>span classn>s/span>span classo>./span>span classn>extract/span>span classo>))/span>/span>span classline>/span>span classline> span classk>def/span> span classn>seek/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>S/span>span classo>)/span> span classk>/span> span classn>duplicate/span>span classo>./span>span classn>peek/span>span classo>(/span>span classn>s/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This models a “store” of values of type code>A/code> indexed by the type code>S/code>. We have the ability to directly access the code>A/code> value under a given code>S/code> using code>peek/code>, and there is a distinguished code>cursor/code> or current position. The comonadic code>extract/code> just reads the value under the code>cursor/code>, and code>duplicate/code> gives us a whole store full of stores such that if we code>peek/code> at any one of them, we get a code>Store/code> whose code>cursor/code> is set to the given code>s/code>. We’re defining a code>seek(s)/code> operation that moves the code>cursor/code> to a given position code>s/code> by taking advantage of code>duplicate/code>./p>p>A use case for this kind of structure might be something like image processing or cellular automata, where code>S/code> might be coordinates into some kind of space (like a two-dimensional image). Then code>extend/code> takes a local computation at the code>cursor/code> and extends it to every point in the space. For example, if we have an operation code>average/code> that peeks at the code>cursor/code>’s immediate neighbors and averages them, then we can apply a low-pass filter to the whole image with code>image.extend(average)/code>./p>p>The type code>A > StoreS,B/code> is also one possible representation of a a hrefhttp://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.package%24%24Lens%24>Lens/a>. I might talk about lenses and a hrefhttp://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.Zipper>zippers/a> in a future post./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/09/30/the-adjunction-that-induces-the-reader-monad/>An Adjunction That Induces the Reader Monad/a>/h1> p classmeta> time classentry-date datetime2015-09-30T07:48:13-04:00>span classdate>span classdate-month>Sep/span> span classdate-day>30/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>7:48 am/span>/time> /p> /header> div classentry-content>p>In writing up part 2 of my a hrefhttp://blog.higher-order.com/blog/2015/06/23/a-scala-comonad-tutorial/>Scala Comonad Tutorial/a>, and coming up with my talk for a hrefhttp://scala.world>Scala World/a>, I idly pondered this question:/p>blockquote>p>If all monads are given by composing adjoint pairs of functors, what adjoint pair of functors forms the `Reader` monad? And if we compose those functors the other way, which comonad do we get?/p>/blockquote>p>Shachaf Ben-Kiki pointed out on IRC that there are at least two ways of doing this. One is via the a hrefhttps://en.wikipedia.org/wiki/Kleisli_category#Kleisli_adjunction>Kleisli construction/a> and the other is via the a hrefhttp://ncatlab.org/nlab/show/Eilenberg-Moore+category>Eilenberg-Moore construction/a>. Dr Eugenia Cheng has a a hrefhttps://www.youtube.com/playlist?listPL54B49729E5102248>fantastic set of videos explaining these constructions/a>. She talks about how for any monad code>T/code> there is a whole category code>Adj(T)/code> of adjunctions that give rise to code>T/code> (with categories as objects and adjoint pairs of functors as the arrows), and the Kleisli category is the initial object in this category while the Eilenberg-Moore category is the terminal object./p>p>So then, searching around for an answer to what exactly the Eilenberg-Moore category for the code>R > ?/code> monad looks like (I think it’s just values of type code>R/code> and functions between them), I came across a hrefhttp://math.stackexchange.com/questions/1274989/what-is-the-eilenberg-moore-category-of-this-diagonal-like-monad>this Mathematics Stack Exchange question/a>, whose answer more or less directly addresses my original question above. The adjunction is a little more difficult to see than the initial/terminal ones, but it’s somewhat interesting, and what follows is an outline of how I convinced myself that it works./p>h2>The adjoint pair/h2>p>Let’s consider the reader monad code>R > ?/code>, which allows us to read a context of type code>R/code>./p>p>The first category involved is em>Set/em> (or em>Hask/em>, or em>Scala/em>). This is just the familiar category where the objects are types (code>A/code>,code>B/code>,code>C/code>, etc.) and the arrows are functions./p>p>The other category is em>Set/R/em>, which is the a hrefhttp://ncatlab.org/nlab/show/overcategory>slice category/a> of em>Set/em> over the type code>R/code>. This is a category whose objects are functions to code>R/code>. So an object code>x/code> in this category is given by a type code>A/code> together with a function of type code>A > R/code>. An arrow from code>x: A > R/code> to code>y: B > R/code> is given by a function code>f: A > B/code> such that code>y(f(a)) x(a)/code> for all code>a:A/code>./p>p>The left adjoint is code>R*/code>, a functor from em>Set/em> to em>Set/R/em>. This functor sends each type code>A/code> to the function code>(p:(R,A)) > p._1/code>, having type code>(R,A) > R/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>rStar/span>span classo>/span>span classkt>A/span>span classo>/span>span classk>:/span> span classo>(/span>span classkt>R/span>span classo>,/span>span classkt>A/span>span classo>)/span> span classk>>/span> span classn>R/span> span classk>/span> span classk>_/span>span classo>./span>span classn>_1/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The right adjoint is code>Π_R/code>, a functor from em>Set/R/em> to em>Set/em>. This functor sends each object code>q: A > R/code> in em>Set/R/em> to the set of functions code>R > A/code> for which code>q/code> is an inverse. This is actually a dependent type inhabited by functions code>p: R > A/code> which satisfy the identity code>q(p(a)) a/code> for all code>a:A/code>./p>h2>Constructing the monad/h2>p>The monad is not exactly easy to see, but if everything has gone right, we should get the code>R > ?/code> reader monad by composing code>Π_R/code> with code>R*/code>./p>p>We start with a type code>A/code>. Then we do code>R*/code>, which gives us the object code>rStarA/code> in the slice category, which you will recall is just code>_._1/code> of type code>(R,A) > R/code>. Then we go back to types via code>Π_R(rStarA)/code> which gives us a dependent type code>P/code> inhabited by functions code>p: R > (R,A)/code>. Now, this looks a lot like an action in the code>State/code> monad. But it’s not. These code>p/code> must satisfy the property that code>_1/code> is their inverse. Which means that the code>R/code> they return must be exactly the code>R/code> they were given. So it’s like a code>State/code> action that is em>read only/em>. We can therefore simplify this to the ordinary (non-dependent) type code>R > A/code>. And now we have our code>Reader/code> monad./p>h2>Constructing the comonad/h2>p>But what about the other way around? What is the comonad constructed by composing code>R*/code> with code>Π_R/code>? Well, since we end up in the slice category, our comonad is actually in that category rather than in em>Set/em>./p>p>We start with an object code>q: A > R/code> in the slice category. Then we go to types by doing code>Π_R(q)/code>. This gives us a dependent type code>P_A/code> which is inhabited by all code>p: R > A/code> such that code>q/code> is their inverse. Then we take code>rStarΠ_R(q)/code> to go back to the slice category and we find ourselves at an object code>f: (R, Π_R(q)) > R/code>, which you’ll recall is implemented as code>_._1/code>. As an endofunctor in em>Set/R/em>, code>λq. rStarΠ_R(q)/code> takes all code>q: A > R/code> to code>p: (R, R > A) > R _._1/code> such that code>p/code> is only defined on code>R > A/code> arguments whose inverse is code>q/code>./p>p>That is, the counit for this comonad on elements code>y: A > R/code> must be a function code>counit: (R, Π_R(y)) > A/code> such that for code>_._1: (R, Π_R(y)) > R/code>, the property code>y compose counit _._1/code> holds. Note that this means that the code>R/code> returned by code>_._1/code> and the code>R/code> returned by code>y/code> must be the same. Recall that code>_._1/code> always returns the first element of its argument, and also recall that the functions in code>Π_R(y)/code> must have code>y/code> as their inverse, so they’re only defined at the first element of the argument to code>_._1/code>. That is code>p._2(x)/code> is only defined when code>x p._1/code>./p>p>If we try to encode that in Scala (ignoring all the “such that”), we get something like:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>p/span>span classk>:/span> span classo>(/span>span classkt>R/span>span classo>,/span> span classkt>R/span> span classo>>/span> span classn>A/span>span classo>))/span>span classk>:/span> span classkt>A/span> span classo>/span>/span>span classline> span classn>p/span>span classo>./span>span classn>_2/span>span classo>(/span>span classn>p/span>span classo>./span>span classn>_1/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This looks a lot like a code>counit/code> for the code>Store/code> comonad! Except what we constructed is not that. Because of the additional requirements imposed by our functors and by the slice category, the second element of code>p/code> can only take an argument that is exactly the first element of code>p/code>. So we can simplify that to code>(R, () > A)/code> or just code>(R, A)/code>. And we now have the familiar code>Coreader/code> comonad./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/23/a-scala-comonad-tutorial/>A Scala Comonad Tutorial, Part 1/a>/h1> p classmeta> time classentry-date datetime2015-06-23T01:15:47-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>23/span>span classdate-suffix>rd/span>, span classdate-year>2015/span>/span> span classtime>1:15 am/span>/time> /p> /header> div classentry-content>p>In chapter 11 of a hrefhttp://manning.com/bjarnason>our book/a>, we talk about monads in Scala. This finally names a pattern that the reader has seen throughout the book and gives it a formal structure. We also give some intuition for what it em>means/em> for something to be a monad. Once you have this concept, you start recognizing it everywhere in the daily business of programming./p>p>Today I want to talk about em>comonads/em>, which are the dual of monads. The utility of comonads in everyday life is not quite as immediately obvious as that of monads, but they definitely come in handy sometimes. Particularly in applications like image processing and scientific computation./p>h2>A monad, upside-down/h2>p>Let’s remind ourselves of what a monad is. A monad is a functor, which just means it has a code>map/code> method:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Functor/span>span classo>/span>span classkt>F/span>span classo>/span>span classk>_/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>x/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>F/span>span classo>/span>span classkt>B/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This has to satisfy the law that code>map(x)(a > a) x/code>, i.e. that mapping the identity function over our functor is a no-op./p>h3>Monads/h3>p>A monad is a functor code>M/code> equipped with two additional polymorphic functions; One from code>A/code> to code>MA/code> and one from code>MMA/code> to code>MA/code>./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Monad/span>span classo>/span>span classkt>M/span>span classo>/span>span classk>_/span>span classo>/span> span classnc>extends/span> span classnc>Functor/span>span classo>/span>span classkt>M/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>unit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline> span classk>def/span> span classn>join/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>mma/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>M/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>M/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Recall that code>join/code> has to satisfy associativity, and code>unit/code> has to be an identity for code>join/code>./p>p>In Scala a monad is often stated in terms of code>flatMap/code>, which is code>map/code> followed by code>join/code>. But I find this formulation easier to explain./p>p>Every monad has the above operations, the so-called em>proper morphisms/em> of a monad, and may also bring to the table some em>nonproper morphisms/em> which give the specific monad some additional capabilities./p>h4>Reader monad/h4>p>For example, the code>Reader/code> monad brings the ability to ask for a value:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Reader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>run/span>span classk>:/span> span classkt>R/span> span classo>>/span> span classn>A/span>span classo>)/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ask/span>span classo>/span>span classkt>R/span>span classo>/span>span classk>:/span> span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>R/span>span classo>/span> span classk>/span> span classnc>Reader/span>span classo>(/span>span classn>r/span> span classk>>/span> span classn>r/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the reader monad is to pass the same context of type code>R/code> to both the outer scope and the inner scope:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>r/span>span classk>:/span> span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>Reader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span>/span>span classline> span classnc>Reader/span>span classo>((/span>span classn>c/span>span classk>:/span>span classkt>R/span>span classo>)/span> span classk>>/span> span classn>r/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>c/span>span classo>)./span>span classn>run/span>span classo>(/span>span classn>c/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>Writer monad/h4>p>The code>Writer/code> monad has the ability to write a value on the side:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Writer/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>(/span>span classn>value/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>log/span>span classk>:/span> span classkt>W/span>span classo>)/span>/span>span classline>/span>span classline>span classk>def/span> span classn>tell/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>W/span>span classo>)/span>span classk>:/span> span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>Unit/span>span classo>/span> span classk>/span> span classnc>Writer/span>span classo>((),/span> span classn>w/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the writer monad is to concatenate the “log” of written values using the monoid for code>W/code> (this is using the code>Monoid/code> class from a hrefhttp://github.com/scalaz/scalaz>Scalaz/a>):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>Writer/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>)/span> span classk>/span>/span>span classline> span classnc>Writer/span>span classo>(/span>span classn>w/span>span classo>./span>span classn>value/span>span classo>./span>span classn>value/span>span classo>,/span> span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>append/span>span classo>(/span>span classn>w/span>span classo>./span>span classn>log/span>span classo>,/span> span classn>w/span>span classo>./span>span classn>value/span>span classo>./span>span classn>log/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And the meaning of code>unit/code> is to write the “empty” log:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>unit/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classk>/span> span classnc>Writer/span>span classo>(/span>span classn>a/span>span classo>,/span> span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>zero/span>span classo>)/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>State monad/h4>p>The code>State/code> monad can both get and set the state:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>get/span>span classo>/span>span classkt>S/span>span classo>/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>S/span>span classo>/span> span classk>/span> span classnc>State/span>span classo>(/span>span classn>s/span> span classk>>/span> span classo>(/span>span classn>s/span>span classo>,/span> span classn>s/span>span classo>))/span>/span>span classline>span classk>def/span> span classn>put/span>span classo>/span>span classkt>S/span>span classo>(/span>span classn>s/span>span classk>:/span> span classkt>S/span>span classo>)/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>Unit/span>span classo>/span> span classk>/span> span classnc>State/span>span classo>(/span>span classk>_/span> span classk>>/span> span classo>((),/span> span classn>s/span>span classo>))/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>The meaning of code>join/code> in the state monad is to give the outer action an opportunity to get and put the state, then do the same for the inner action, making sure any subsequent actions see the changes made by previous ones./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>run/span>span classk>:/span> span classkt>S/span> span classo>>/span> span classo>(/span>span classn>A/span>span classo>,/span> span classn>S/span>span classo>))/span>/span>span classline>/span>span classline>span classk>def/span> span classn>join/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>(/span>span classn>v1/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>State/span>span classo>/span>span classkt>S/span>,span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>State/span>span classo>(/span>span classn>s1/span> span classk>>/span> span classo>{/span>/span>span classline> span classk>val/span> span classo>(/span>span classn>v2/span>span classo>,/span> span classn>s2/span>span classo>)/span> span classk>/span> span classn>v1/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>s1/span>span classo>)/span>/span>span classline> span classn>v2/span>span classo>./span>span classn>run/span>span classo>(/span>span classn>s2/span>span classo>)/span>/span>span classline> span classo>})/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h4>Option monad/h4>p>The code>Option/code> monad can terminate without an answer:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>none/span>span classo>/span>span classkt>A/span>span classo>/span>span classk>:/span> span classkt>Option/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>None/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>That’s enough examples of monads. Let’s now turn to comonads./p>h2>Comonads/h2>p>A comonad is the same thing as a monad, only backwards:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>trait/span> span classnc>Comonad/span>span classo>/span>span classkt>W/span>span classo>/span>span classk>_/span>span classo>/span> span classnc>extends/span> span classnc>Functor/span>span classo>/span>span classkt>W/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>w/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>A/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>wa/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>A/span>span classo>)/span>span classk>:/span> span classkt>W/span>span classo>/span>span classkt>W/span>span classo>/span>span classkt>A/span>span classo>/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that counit is pronounced “co-unit”, not “cow-knit”. It’s also sometimes called code>extract/code> because it allows you to get a value of type code>A/code> em>out of/em> a code>WA/code>. While with monads you can generally only put values in and not get them out, with comonads you can generally only get them out and not put them in./p>p>And instead of being able to code>join/code> two levels of a monad into one, we can code>duplicate/code> one level of a comonad into two./p>p>Kind of weird, right? This also has to obey some laws. We’ll get to those later on, but let’s first look at some actual comonads./p>h3>The identity comonad/h3>p>A simple and obvious comonad is the dumb wrapper (the identity comonad):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Id/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>a/span>span classk>:/span> span classkt>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Id/span>span classo>/span>span classkt>B/span>span classo>/span> span classk>/span> span classnc>Id/span>span classo>(/span>span classn>f/span>span classo>(/span>span classn>a/span>span classo>))/span>/span>span classline> span classk>def/span> span classn>counit/span>span classk>:/span> span classkt>A/span> span classo>/span> span classn>a/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Id/span>span classo>/span>span classkt>Id/span>span classo>/span>span classkt>A/span>span classo>/span> span classk>/span> span classnc>Id/span>span classo>(/span>span classk>this/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This one is also the identity em>monad/em>. code>Id/code> doesn’t have any functionality other than the proper morphisms of the (co)monad and is therefore not terribly interesting. We can get the value out with our code>counit/code>, and we can vacuously code>duplicate/code> by decorating our existing code>Id/code> with another layer./p>h3>The reader comonad/h3>p>There’s a comonad with the same capabilities as the reader monad, namely that it allows us to ask for a value:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>extract/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>ask/span>span classk>:/span> span classkt>R/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>B/span>span classo>/span> span classk>/span> span classnc>Coreader/span>span classo>(/span>span classn>f/span>span classo>(/span>span classn>extract/span>span classo>),/span> span classn>ask/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>, span classkt>Coreader/span>span classo>/span>span classkt>R/span>, span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Coreader/span>span classo>(/span>span classk>this/span>span classo>,/span> span classn>ask/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>It should be obvious how we can give a code>Comonad/code> instance for this (I’m using the a hrefhttps://github.com/non/kind-projector>Kind Projector compiler plugin/a> to make the syntax look a little nicer than Vanilla Scala):/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>coreaderComonad/span>span classo>/span>span classkt>R/span>span classo>/span>span classk>:/span> span classkt>Comonad/span>span classo>/span>span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>?/span>span classo>/span> span classk>/span>/span>span classline> span classk>new/span> span classnc>Comonad/span>span classo>/span>span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>?/span>span classo>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>A/span>,span classkt>B/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span> span classk>/span> span classn>c/span> span classn>map/span> span classn>f/span>/span>span classline> span classk>def/span> span classn>counit/span>span classo>/span>span classkt>A/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span> span classn>c/span>span classo>./span>span classn>extract/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classo>(/span>span classn>c/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>)/span> span classk>/span> span classn>c/span>span classo>./span>span classn>duplicate/span>/span>span classline> span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Arguably, this is much more straightforward in Scala than the reader monad. In the reader em>monad/em>, the code>ask/code> function is the identity function. That’s saying “once the code>R/code> value is available, return it to me”, making it available to subsequent code>map/code> and code>flatMap/code> operations. But in code>Coreader/code>, we don’t have to pretend to have an code>R/code> value. It’s just right there and we can look at it./p>p>So code>Coreader/code> just wraps up some value of type code>A/code> together with some additional context of type code>R/code>. Why is it important that this is a em>comonad/em>? What is the meaning of code>duplicate/code> here?/p>p>To see the meaning of code>duplicate/code>, notice that it puts the whole code>Coreader/code> in the value slot (in the code>extract/code> portion). So any subsequent code>extract/code> or code>map/code> operation will be able to observe both the value of type code>A/code> and the context of type code>R/code>. We can think of this as passing the context along to those subsequent operations, which is analogous to what the reader monad does./p>p>In fact, just like code>map/code> followed by code>join/code> is usually expressed as code>flatMap/code>, by the same token code>duplicate/code> followed by code>map/code> is usually expressed as a single operation, code>extend/code>:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>(/span>span classn>extract/span>span classk>:/span> span classkt>A/span>span classo>,/span> span classn>ask/span>span classk>:/span> span classkt>R/span>span classo>)/span> span classo>{/span>/span>span classline> span classo>.../span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Coreader/span>span classo>/span>span classkt>R/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>duplicate/span> span classn>map/span> span classn>f/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Notice that the type signature of code>extend/code> looks like code>flatMap/code> with the direction of code>f/code> reversed. And just like we can chain operations in a monad using code>flatMap/code>, we can chain operations in a comonad using code>extend/code>. In code>Coreader/code>, code>extend/code> is making sure that code>f/code> can use the context of type code>R/code> to produce its code>B/code>./p>p>Chaining operations this way using code>flatMap/code> in a monad is sometimes called em>Kleisli composition/em>, and chaining operations using code>extend/code> in a comonad is called em>coKleisli/em> composition (or just Kleisli composition in a comonad)./p>p>The name code>extend/code> refers to the fact that it takes a “local” computation that operates on some structure and “extends” that to a “global” computation that operates on all substructures of the larger structure./p>h3>The writer comonad/h3>p>Just like the writer monad, the writer comonad can append to a log or running tally using a monoid. But instead of keeping the log always available to be appended to, it uses the same trick as the reader monad by building up an operation that gets executed once a log becomes available:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>case/span> span classk>class/span> span classnc>Cowriter/span>span classo>/span>span classkt>W:Monoid/span>,span classkt>A/span>span classo>(/span>span classn>tell/span>span classk>:/span> span classkt>W/span> span classo>>/span> span classn>A/span>span classo>)/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>map/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>A/span> span classo>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>B/span>span classo>/span> span classk>/span> span classnc>Cowriter/span>span classo>(/span>span classn>tell/span> span classn>andThen/span> span classn>f/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>extract/span> span classk>/span> span classn>tell/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>zero/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>duplicate/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>, span classkt>Cowriter/span>span classo>/span>span classkt>W/span>, span classkt>A/span>span classo>/span> span classk>/span>/span>span classline> span classnc>Cowriter/span>span classo>(/span>span classn>w1/span> span classk>>/span> span classnc>Cowriter/span>span classo>(/span>span classn>w2/span> span classk>>/span> span classn>tell/span>span classo>(/span>span classnc>Monoid/span>span classo>/span>span classkt>W/span>span classo>./span>span classn>append/span>span classo>(/span>span classn>w1/span>span classo>,/span> span classn>w2/span>span classo>))))/span>/span>span classline> span classk>def/span> span classn>extend/span>span classo>/span>span classkt>B/span>span classo>(/span>span classn>f/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>A/span>span classo>/span> span classk>>/span> span classn>B/span>span classo>)/span>span classk>:/span> span classkt>Cowriter/span>span classo>/span>span classkt>W/span>,span classkt>B/span>span classo>/span> span classk>/span>/span>span classline> span classn>duplicate/span> span classn>map/span> span classn>f/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Note that code>duplicate/code> returns a whole code>Cowriter/code> from its constructed code>run/code> function, so the meaning is that subsequent operations (composed via code>map/code> or code>extend/code>) have access to exactly one code>tell/code> function, which appends to the existing log or tally. For example, code>foo.extend(_.tell(hi))/code> will append code>hi/code> to the log of code>foo/code>./p>h2>Comonad laws/h2>p>The comonad laws are analogous to the monad laws:/p>ol>li>Left identity: code>wa.duplicate.extract wa/code>/li>li>Right identity: code>wa.extend(extract) wa/code>/li>li>Associativity: code>wa.duplicate.duplicate wa.extend(duplicate)/code>/li>/ol>p>It can be hard to get an intuition for what these laws em>mean/em>, but in short they mean that (co)Kleisli composition in a comonad should be associative and that code>extract/code> (a.k.a. code>counit/code>) should be an identity for it./p>p>Very informally, both the monad and comonad laws mean that we should be able to compose our programs top-down or bottom-up, or any combination thereof, and have that mean the same thing regardless./p>h2>Next time…/h2>p>In a hrefhttp://blog.higher-order.com/blog/2015/10/04/scala-comonad-tutorial-part-2/>part 2/a> we’ll look at some more examples of comonads and follow some of the deeper connections. Like what’s the relationship between the reader monad and the reader comonad, or the writer monad and the writer comonad? They’re not identical, but they seem to do all the same things. Are they equivalent? Isomorphic? Something else?/p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/18/easy-performance-wins-with-scalaz/>Easy Performance Wins With Scalaz/a>/h1> p classmeta> time classentry-date datetime2015-06-18T15:09:21-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>18/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>3:09 pm/span>/time> /p> /header> div classentry-content>p>I’ve found that if I’m using code>scala.concurrent.Future/code> in my code, I can get some really easy performance gains by just switching to code>scalaz.concurrent.Task/code> instead, particularly if I’m chaining them with code>map/code> or code>flatMap/code> calls, or with code>for/code> comprehensions./p>h2>Jumping into thread pools/h2>p>Every code>Future/code> is basically some work that needs to be submitted to a thread pool. When you call code>futureA.flatMap(a > futureB)/code>, both code>FutureA/code> and code>FutureB/code> need to be submitted to the thread pool, even though they are not running concurrently and could theoretically run on the same thread. This context switching takes a bit of time./p>h2>Jumping on trampolines/h2>p>With code>scalaz.concurrent.Task/code> you have a bit more control over when you submit work to a thread pool and when you actually want to continue on the thread that is already executing a code>Task/code>. When you say code>taskA.flatMap(a > taskB)/code>, the code>taskB/code> will by default just continue running on the same thread that was already executing code>taskA/code>. If you explicitly want to dip into the thread pool, you have to say so with code>Task.fork/code>./p>p>This works since a code>Task/code> is not a concurrently running computation. It’s a em>description/em> of a computation—a sequential list of instructions that may include instructions to submit some of the work to thread pools. The work is actually executed by a tight loop in code>Task/code>’s code>run/code> method. This loop is called a em>trampoline/em> since every step in the code>Task/code> (that is, every subtask) returns control to this loop./p>p>Jumping on a trampoline is a lot faster than jumping into a thread pool, so whenever we’re composing code>Future/code>s with code>map/code> and code>flatMap/code>, we can just switch to code>Task/code> and make our code faster./p>h2>Making fewer jumps/h2>p>But sometimes we know that we want to continue on the same thread and we don’t want to spend the time jumping on a trampoline at every step. To demonstrate this, I’ll use the Ackermann function. This is not necessarily a good use case for code>Future/code> but it shows the difference well./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classscala>span classline>span classc1>// Only defined for positive `m` and `n`/span>/span>span classline>span classk>def/span> span classn>ackermann/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Int/span> span classo>/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>n/span> span classo>+/span> span classmi>1/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>ackermann/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classn>ackermann/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>ackermann/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This function is supposed to terminate for all positive code>m/code> and code>n/code>, but if they are modestly large, this recursive definition overflows the stack. We could use futures to alleviate this, jumping into a thread pool instead of making a stack frame at each step:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>import/span> span classnn>scala.concurrent.Future/span>/span>span classline>span classk>import/span> span classnn>scala.concurrent.ExecutionContext.Implicits.global/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ackermannF/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Future/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classnc>Future/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>))./span>span classn>flatMap/span>span classo>(/span>span classn>identity/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classk>for/span> span classo>{/span>/span>span classline> span classn>x/span> span classk><-/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))/span>/span>span classline> span classn>y/span> span classk><-/span> span classn>x/span>/span>span classline> span classn>z/span> span classk><-/span> span classnc>Future/span>span classo>(/span>span classn>ackermannF/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>y/span>span classo>))/span>/span>span classline> span classn>r/span> span classk><-/span> span classn>z/span>/span>span classline> span classo>}/span> span classk>yield/span> span classn>r/span>/span>span classline> span classo>}/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Since there’s no actual concurrency going on here, we can make this instantly faster by switching to code>Task/code> instead, using a trampoline instead of a thread pool:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>import/span> span classnn>scalaz.concurrent.Task/span>span classo>,/span> span classnc>Task/span>span classo>./span>span classk>_/span>/span>span classline>/span>span classline>span classk>def/span> span classn>ackermannT/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>now/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>))/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>))./span>span classn>flatMap/span> span classo>{/span> span classn>x/span> span classk>>/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannT/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>x/span>span classo>))/span> span classo>}/span>/span>span classline> span classo>}/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>But even here, we’re making too many jumps back to the trampoline with code>suspend/code>. We don’t actually need to suspend and return control to the trampoline at each step. We only need to do it enough times to avoid overflowing the stack. Let’s say we know how large our stack can grow:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>val/span> span classn>maxStack/span> span classk>/span> span classmi>512/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>We can then keep track of how many recursive calls we’ve made, and jump on the trampoline only when we need to:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>/pre>/td>td classcode>pre>code classscala>span classline>span classk>def/span> span classn>ackermannO/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span> span classo>{/span>/span>span classline> span classk>def/span> span classn>step/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>stack/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span>/span>span classline> span classk>if/span> span classo>(/span>span classn>stack/span> span classo>>/span> span classn>maxStack/span>span classo>)/span>/span>span classline> span classn>suspend/span>span classo>(/span>span classn>ackermannO/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>))/span>/span>span classline> span classk>else/span> span classn>go/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>,/span> span classn>stack/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>def/span> span classn>go/span>span classo>(/span>span classn>m/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>n/span>span classk>:/span> span classkt>Int/span>span classo>,/span> span classn>stack/span>span classk>:/span> span classkt>Int/span>span classo>)/span>span classk>:/span> span classkt>Task/span>span classo>/span>span classkt>Int/span>span classo>/span> span classk>/span>/span>span classline> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>match/span> span classo>{/span>/span>span classline> span classk>case/span> span classo>(/span>span classmi>0/span>span classo>,/span> span classk>_/span>span classo>)/span> span classk>>/span> span classn>now/span>span classo>(/span>span classn>n/span> span classo>+/span> span classmi>1/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classmi>0/span>span classo>)/span> span classk>>/span> span classn>step/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classmi>1/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classk>case/span> span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>)/span> span classk>>/span> span classk>for/span> span classo>{/span>/span>span classline> span classn>internalRec/span> span classk><-/span> span classn>step/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classn>result/span> span classk><-/span> span classn>step/span>span classo>(/span>span classn>m/span> span classo>-/span> span classmi>1/span>span classo>,/span> span classn>internalRec/span>span classo>,/span> span classn>stack/span>span classo>)/span>/span>span classline> span classo>}/span> span classk>yield/span> span classn>result/span>/span>span classline> span classo>}/span>/span>span classline> span classn>go/span>span classo>(/span>span classn>m/span>span classo>,/span> span classn>n/span>span classo>,/span> span classmi>0/span>span classo>)/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>How fast is it?/h2>p>I did some comparisons using a hrefhttps://github.com/google/caliper>Caliper/a> and made this pretty graph for you:/p>p>img src/images/futuretaskplot.png>/p>p>The horizontal axis is the number of steps, and the vertical axis is the mean time that number of steps took over a few thousand runs./p>p>This graph shows that code>Task/code> is slightly faster than code>Future/code> for submitting to thread pools (blue and yellow lines marked em>Future/em> and em>Task/em> respectively) only for very small tasks; up to about when you get to 50 steps, when (on my Macbook) both futures and tasks cross the 30 μs threshold. This difference is probably due to the fact that a code>Future/code> is a running computation while a code>Task/code> is partially constructed up front and explicitly code>run/code> later. So with the code>Future/code> the threads might just be waiting for more work. The overhead of code>Task.run/code> seems to catch up with us at around 50 steps./p>p>But honestly the difference between these two lines is not something I would care about in a real application, because if we jump on the trampoline instead of submitting to a thread pool (green line marked em>Trampoline/em>), things are em>between one and two orders of magnitude faster/em>./p>p>If we only jump on the trampoline when we really need it (red line marked em>Optimized/em>), we can gain another order of magnitude. Compared to the original naïve version that always goes to the thread pool, strong>em>this is now the difference between running your program on a 10 MHz machine and running it on a 1 GHz machine/em>/strong>./p>p>If we measure without using any code>Task/code>/code>Future/code> at all, the line tracks the em>Optimized/em> red line pretty closely then shoots to infinity around 1000 (or however many frames fit in your stack space) because the program crashes at that point./p>p>In summary, if we’re smart about trampolines vs thread pools, code>Future/code> vs code>Task/code>, and optimize for our stack size, we can go from milliseconds to microseconds with not very much effort. Or seconds to milliseconds, or weeks to hours, as the case may be./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/06/16/pulling-out-of-functional-programming-in-java/>Pulling Out of Functional Programming in Java/a>/h1> p classmeta> time classentry-date datetime2015-06-16T11:37:34-04:00>span classdate>span classdate-month>Jun/span> span classdate-day>16/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:37 am/span>/time> /p> /header> div classentry-content>p>After giving it a lot of thought I have come to the conclusion that I won’t be involved in a hrefhttp://manning.com/saumont>“Functional Programming in Java”/a>. There are many reasons, including that I just don’t think I can spend the time to make this a good book. Looking at all the things I have scheduled for the rest of the year, I can’t find the time to work on it./p>p>More depressingly, the thought of spending a year or more writing another book makes me anxious. I know from experience that making a book (at least a good one) is really hard and takes up a lot of mental energy. Maybe one day there will be a book that I will want to forego a year of evenings and weekends for, but today is not that day./p>p>Originally, the content of FPiJ was going to be based on “Functional Programming in Scala”, but after some discussion with the publisher I think we were all beginning to see that this book deserved its own original content specifically on an FP style in Java./p>p>I really do think such a thing deserves its own original book. Since Java is strictly less suitable for functional programming than Scala is, a book on FP in Java will have to lay a lot of groundwork that we didn’t have to do with FPiS, and it will have to forego a lot of the more advanced topics./p>p>I wish the author of that book, and the publisher, all the best and I hope they do well. I’m sorry to let you all down, but I’m sure this is for the best./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/03/06/a-companion-booklet-to-functional-programming-in-scala/>A Companion Booklet to FPiS/a>/h1> p classmeta> time classentry-date datetime2015-03-06T15:17:35-05:00>span classdate>span classdate-month>Mar/span> span classdate-day>6/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>3:17 pm/span>/time> /p> /header> div classentry-content>p>Our book, a hrefhttp://manning.com/bjarnason>Functional Programming in Scala/a>, relies heavily on exercises. Hints and answers for those exercises are not actually in the book, but are a hrefhttp://github.com/fpinscala/fpinscala>freely available on GitHub/a> under a permissive MIT license. Likewise, we have written chapter notes that we reference throughout the book and made them a hrefhttp://github.com/fpinscala/fpinscala/wiki>available as a community-editable wiki/a>./p>p>Naturally, readers get the most out of this book by downloading the source code from GitHub and doing the exercises as they read. But a number of readers have made the comment that they wish they could have the hints and answers with them when they read the book on the train to and from work, on a long flight, or wherever there is no internet connection or it’s not convenient to use a computer./p>p>It is of course entirely possible to print out the chapter notes, hints, and exercises, and take them with you either as a hardcopy or as a PDF to use on a phone or tablet. Well, I’ve taken the liberty of doing that work for you. I wrote a little script to concatenate all the chapter notes, errata, hints, and answers into Markdown files and then just printed them all to a single document, tweaking a few things here and there. I’m calling this em>A companion booklet to “Functional Programming in Scala”/em>. It is released under the same a hrefhttps://github.com/fpinscala/fpinscala/blob/master/LICENSE>MIT license/a> as the content it aggregates. This means you’re free to copy it, distribute or sell it, or basically do whatever you want with it. The Markdown source of the manuscript is a hrefhttps://github.com/runarorama/fpiscompanion>available on my GitHub/a>./p>p>I have made a hrefhttps://leanpub.com/fpinscalacompanion>an electronic version of this booklet available on Leanpub/a> as as a PDF, ePub, and Kindle file on a pay-what-you-want basis (minimum of $0.99). It has full color syntax highlighting throughout and a few little tweaks to make it format nicely. The paper size is standard US Letter which makes it easy to print on most color printers. If you choose to buy the booklet from Leanpub, they get a small fee, a small portion of the proceeds goes to support a hrefhttp://www.libertyinnorthkorea.org/>Liberty in North Korea/a>, and the rest goes to yours truly. You’ll also get updates when those inevitably happen./p>p>If you don’t care about any of that, a href/assets/fpiscompanion.pdf>you can grab the PDF from here with my compliments/a>./p>p>The booklet is also a hrefhttps://www.createspace.com/5325404>available from CreateSpace/a> or a hrefhttp://www.amazon.com/companion-booklet-Functional-Programming-Scala/dp/1508537569>Amazon/a> as a full color printed paperback. This comes in a nicely bound glossy cover for just a little more than the price of printing (they print it on demand for you). I’ve ordered one and I’m really happy with the quality of this print:/p>p>img src/images/bookletcover.jpg>img src/images/chapternotes.jpg>img src/images/exercises.jpg>/p>p>The print version is of course under the same permissive license, so you can make copies of it, make derivative works, or do whatever you want. It’s important to note that with this booklet I’ve not done anything other than design a little cover and then em>literally print out this freely available content/em> and upload it to Amazon, which anybody could have done (and you still can if you want)./p>p>I hope this makes em>Functional Programming in Scala/em> more useful and more enjoyable for more people./p>/div> /article> article> header> h1 classentry-title>a href/blog/2015/02/08/a-better-reading-list-with-mathematica/>A Better Reading List With Mathematica/a>/h1> p classmeta> time classentry-date datetime2015-02-08T11:04:00-05:00>span classdate>span classdate-month>Feb/span> span classdate-day>8/span>span classdate-suffix>th/span>, span classdate-year>2015/span>/span> span classtime>11:04 am/span>/time> /p> /header> div classentry-content>p>Like a lot of people, I keep a list of books I want to read. And because there are a great many more books that interest me than I can possibly read in my lifetime, this list has become quite long./p>p>In the olden days of brick-and-mortar bookstores and libraries, I would discover books to read by browsing shelves and picking up what looked interesting at the time. I might even find something that I knew was on my list. “Oh, I’ve been meaning to read that!”/p>p>The Internet changes this dynamic dramatically. It makes it much easier for me to discover books that interest me, and also to access any book that I might want to read, instantly, anywhere. At any given time, I have a couple of books that I’m “currently reading”, and when I finish one I can start another immediately. I use Goodreads to manage my to-read list, and it’s easy for me to scroll through the list and pick out my next book./p>p>But again, this list is very long. So I wanted a good way to filter out books I will really never read, and sort it such that the most “important” books in some sense show up first. Then every time I need a new book I could take the first one from the list and make a binary decision: either “I will read this right now”, or “I am never reading this”. In the latter case, if a book interests me enough at a later time, I’m sure it will find its way back onto my list./p>p>The problem then is to find a good metric by which to rank books. Goodreads lets users rank books with a star-rating from 1 to 5, and presents you with an average rating by which you can sort the list. The problem is that a lot of books that interest me have only one rating and it’s 5 stars, giving the book an “average” of 5.0. So if I go with that method I will be perpetually reading obscure books that one other person has read and loved. This is not necessarily a bad thing, but I do want to branch out a bit./p>p>Another possibility is to use the number of ratings to calculate a a hrefhttp://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval>confidence interval/a> for the average rating. For example, using the a hrefhttp://www.evanmiller.org/how-not-to-sort-by-average-rating.html>Wilson score/a> I could find an upper and lower bound code>s1/code> and code>s2/code> (higher and lower than the average rating, respectively) that will let me say “I am 95% sure that any random sample of readers of an equal size would give an average rating between code>s1/code> and code>s2/code>.” I could then sort the list by the lower bound code>s1/code>./p>p>But this method is dissatisfactory for a number of reasons. First, it’s not clear how to fit star ratings to such a measure. If we do the naive thing and count a 1-star rating as 1/5 and a 5 star rating as 5/5, that counts a 1-star rating as a “partial success” in some sense. We could discard 1-stars as 0, and count 2, 3, 4, and 5 stars as 25%, 50%, 75%, and 100%, respectively./p>p>But even if we did make it fit somehow, it turns out that if you take em>any moderately popular book/em> on Goodreads at random, it will have an average rating somewhere close to 4. I could a hrefhttp://stephsun.com/silverizing.html>manufacture a prior/a> based on this knowledge and use that instead of the normal distribution or the Jeffreys prior in the confidence interval, but that would still not be a very good ranking because a hrefhttp://stephsun.com/metascores.html>reader review metascores are meaningless/a>./p>p>In the article a hrefhttp://stephsun.com/metascores.html>“Reader review metascores are meaningless”/a>, Stephanie Shun suggests using the em>percentage of 5-star ratings/em> as the relevant metric rather than the average rating. This is a good suggestion, since even a single 5-star rating carries a lot of actionable information whereas an average rating close to 4.0 carries very little./p>p>I can then use the Wilson score directly, counting a 5-star rating as a successful trial and any other rating as a failed one. I can then just use the normal distribution instead of working with an artisanally curated prior./p>p>Mathematica makes it easy to generate the Wilson score. Here, code>pos/code> is the number of positive trials (number of 5-star ratings), code>n/code> is the number of total ratings, and code>confidence/code> is the desired confidence percentage. I’m taking the lower bound of the confidence interval to get my score./p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Wilson/span>span classp>/span>span classnv>pos_/span>span classp>,/span>span classw> /span>span classnv>n_/span>span classp>,/span>span classw> /span>span classnv>confidence_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>/span>span classline>span classw> /span>span classn>If/span>span classp>/span>span classn>n/span>span classw> /span>span classo>/span>span classw> /span>span classmi>0/span>span classw> /span>span classo>||/span>span classw> /span>span classn>n/span>span classw> /span>span classerr></span>span classw> /span>span classn>pos/span>span classp>,/span>span classw> /span>span classmi>0/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>z/span>span classw> /span>span classo>/span>span classw> /span>span classn>Quantile/span>span classp>/span>span classn>NormalDistribution/span>span classp>,/span>span classw> /span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classp>(/span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classn>confidence/span>span classp>)/span>span classo>//span>span classmi>2/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>p/span>span classw> /span>span classo>/span>span classw> /span>span classn>pos/span>span classo>//span>span classn>n/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classp>(/span>span classo>-/span>span classp>(/span>span classn>z/span>span classw> /span>span classn>Sqrt/span>span classp>(/span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classp>(/span>span classmi>4/span>span classw> /span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classp>(/span>span classmi>1/span>span classw> /span>span classo>-/span>span classw> /span>span classn>p/span>span classp>)/span>span classw> /span>span classn>p/span>span classp>)/span>span classo>//span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classp>(/span>span classmi>2/span>span classw> /span>span classn>n/span>span classp>)/span>span classw> /span>span classo>+/span>span classw> /span>span classn>p/span>span classp>)/span>span classw> /span>span classo>//span>span classw>/span>/span>span classline>span classw> /span>span classp>(/span>span classn>z/span>span classo>^/span>span classmi>2/span>span classo>//span>span classn>n/span>span classw> /span>span classo>+/span>span classw> /span>span classmi>1/span>span classp>)/span>span classw>/span>/span>span classline>span classw> /span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now I just need to get the book data from Goodreads. Fortunately, a hrefhttps://www.goodreads.com/api>it has a pretty rich API/a>. I just need a developer key, which anyone can get for free./p>p>For example, to get the ratings for a given book code>id/code>, we can use their XML api for books and pattern match on the result to get the ratings by score:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Ratings/span>span classp>/span>span classnv>id_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classn>id/span>span classp>/span>span classw> /span>span classo>/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>raw/span>span classw> /span>span classo>/span>span classw> /span>span classn>Cases/span>span classp>/span>span classn>Import/span>span classp>/span>span classn>ToString/span>span classp>/span>span classn>StringForm/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"http://www.goodreads.com/book/show.xml?key``&id``"/span>span classp>,/span>span classw> /span>span classn>key/span>span classp>,/span>span classw> /span>span classn>id/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"rating_dist"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>d_/span>span classp>}/span>span classw> /span>span classo>->/span>span classw> /span>span classn>d/span>span classp>,/span>span classw> /span>span classn>Infinity/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw> /span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classn>data/span>span classw> /span>span classo>/span>span classw> /span>span classn>StringSplit/span>span classp>/span>span classnv>#/span>span classp>,/span>span classw> /span>span classs>":"/span>span classp>/span>span classw> /span>span classo>&/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>StringSplit/span>span classp>/span>span classn>raw/span>span classp>,/span>span classw> /span>span classs>"|"/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classp>},/span>span classw> /span>span classn>Block/span>span classp>{},/span>span classw> /span>span classn>Pause/span>span classp>/span>span classmi>1/span>span classp>;/span>span classw>/span>/span>span classline>span classw> /span>span classn>FromDigits/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>Association/span>span classp>/span>span classn>Rule/span>span classw> /span>span classo>@@@/span>span classw> /span>span classn>First/span>span classp>/span>span classn>data/span>span classp>;/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Here, code>key/code> is my Goodreads developer API key, defined elsewhere. I put a code>Pause1/code> in the call since Goodreads throttles API calls so you can’t make more than one call per second to each API endpoint. I’m also memoizing the result, by assigning to code>Ratingsid/code> in the global environment./p>p>code>Ratings/code> will give us an association list with the number of ratings for each score from 1 to 5, together with the total. For example, for the first book in their catalogue, em>Harry Potter and the Half-Blood Prince/em>, here are the scores:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>In/span>span classp>/span>span classmi>1/span>span classp>/span>span classo>:/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classmi>1/span>span classp>/span>span classw>/span>/span>span classline>/span>span classline>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classo>/span>span classw> /span>span classerr></span>span classo>|/span>span classs>"5"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>782740/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"4"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>352725/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"3"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>111068/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"2"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>17693/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"1"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>5289/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classs>"total"/span>span classw> /span>span classo>->/span>span classw> /span>span classmi>1269515/span>span classo>|/span>span classerr>>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Sweet. Let’s see how Harry Potter #6 would score with our rating:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>In/span>span classp>/span>span classmi>2/span>span classp>/span>span classo>:/span>span classw> /span>span classn>Wilson/span>span classp>/span>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classs>"5"/span>span classp>,/span>span classw> /span>span classn>Out/span>span classp>/span>span classmi>1/span>span classp>/span>span classs>"total"/span>span classp>,/span>span classw> /span>span classmf>0.95/span>span classp>/span>span classw>/span>/span>span classline>/span>span classline>span classn>Out/span>span classp>/span>span classmi>2/span>span classp>/span>span classo>/span>span classw> /span>span classmf>0.61572/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>So Wilson is 95% confident that in any random sample of about 1.2 million Harry Potter readers, at least 61.572% of them would give em>The Half-Blood Prince/em> a 5-star rating. That turns out to be a pretty high score, so if this book were on my list (which it isn’t), it would feature pretty close to the very top./p>p>But now the score for a relatively obscure title is too low. For example, the lower bound of the 95% confidence interval for a single-rating 5-star book will be 0.206549, which will be towards the bottom of any list. This means I would never get to any of the obscure books on my reading list, since they would be edged out by moderately popular books with an average rating close to 4.0./p>p>See, if I’ve picked a book that em>I want to read/em>, I’d consider five ratings that are all five stars a much stronger signal than the fact that people who like Harry Potter enough to read 5 previous books loved the 6th one. Currently the 5*5 book will score 57%, a bit weaker than the Potter book’s 62%./p>p>I can fix this by lowering the confidence level. Because honestly, I don’t need a high confidence in the ranking. I’d rather err on the side of picking up a deservedly obscure book than to miss out on a rare gem. Experimenting with this a bit, I find that a confidence around 80% raises the obscure books enough to give me an interesting mix. For example, a 5*5 book gets a 75% rank, while the Harry Potter one stays at 62%./p>p>I’m going to call that the em>Rúnar rank/em> of a given book. The Rúnar rank is defined as the lower bound of the em>1-1/q/em> Wilson confidence interval for scoring in the em>q/em>th em>q/em>-quantile. In the special case of Goodreads ratings, it’s the 80% confidence for a 5-star rating./p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>RunarRank/span>span classp>/span>span classnv>id_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>With/span>span classp>{/span>span classn>ratings/span>span classw> /span>span classo>/span>span classw> /span>span classn>Ratings/span>span classp>/span>span classn>id/span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classn>Wilson/span>span classp>/span>span classn>ratings/span>span classp>/span>span classs>"5"/span>span classp>,/span>span classw> /span>span classn>ratings/span>span classp>/span>span classs>"total"/span>span classp>,/span>span classw> /span>span classmf>.8/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Unfortunately, there’s no way to get the rank of all the books in my reading list in one call to the Goodreads API. And when I asked them about it they basically said “you can’t do that”, so I’m assuming that feature will not be added any time soon. So I’ll have to get the reading list first, then call code>RunarRank/code> for each book’s code>id/code>. In Goodreads, books are managed by “shelves”, and the API allows getting the contents of a given shelf, 200 books at a time:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>GetShelf/span>span classp>/span>span classnv>user_/span>span classp>,/span>span classw> /span>span classnv>shelf_/span>span classp>/span>span classw> /span>span classo>:/span>span classw>/span>/span>span classline>span classw> /span>span classn>With/span>span classp>{/span>span classn>raw/span>span classw> /span>span classo>/span>span classw> /span>/span>span classline>span classw> /span>span classn>Cases/span>span classp>/span>span classn>Import/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>ToString/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>StringForm/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classerr>"/span>span classn>http/span>span classerr>:/span>span classo>///span>span classn>www/span>span classerr>./span>span classn>goodreads/span>span classerr>./span>span classn>com/span>span classo>//span>span classn>review/span>span classo>//span>span classn>list/span>span classerr>./span>span classn>xml/span>span classo>?/span>span classn>v/span>span classo>/span>span classmi>2/span>span classo>&/span>span classn>key/span>span classo>/span>span classerr>``/span>span classo>&/span>span classn>id/span>span classo>/span>span classerr>``/span>span classo>&/span>span classerr>\/span>span classw>/span>/span>span classline>span classn>shelf/span>span classo>/span>span classerr>``/span>span classo>&/span>span classn>sort/span>span classo>/span>span classnv>avg_rating/span>span classo>&/span>span classn>order/span>span classo>/span>span classn>d/span>span classo>&/span>span classnv>per_page/span>span classo>/span>span classmi>200/span>span classerr>"/span>span classp>,/span>span classw> /span>span classn>key/span>span classp>,/span>span classw> /span>span classn>user/span>span classp>,/span>span classw> /span>span classn>shelf/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"book"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>___/span>span classp>,/span>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>id_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"title"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>title_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classs>"average_rating"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>avg_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"authors"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"author"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>___/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>XMLElement/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classs>"name"/span>span classp>,/span>span classw> /span>span classnv>_/span>span classp>,/span>span classw> /span>span classp>{/span>span classnv>author_/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>},/span>span classw> /span>span classnv>___/span>span classp>}/span>span classw> /span>span classo>->/span>span classw> /span>span classp>{/span>span classs>"id"/span>span classw> /span>span classo>->/span>span classw> /span>/span>span classline>span classw> /span>span classn>id/span>span classp>,/span>span classw> /span>span classs>"title"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>title/span>span classp>,/span>span classw> /span>span classs>"author"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>author/span>span classp>,/span>span classw> /span>span classs>"avg"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>avg/span>span classp>},/span>span classw> /span>/span>span classline>span classw> /span>span classn>Infinity/span>span classp>},/span>span classw> /span>span classn>Association/span>span classw> /span>span classo>/@/span>span classw> /span>span classn>raw/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>I’m doing a bunch of XML pattern matching here to get the code>id/code>, code>title/code>, code>average_rating/code>, and first code>author/code> of each book. Then I put that in an association list. I’m getting only the top-200 books on the list by average rating (which currently is about half my list)./p>p>With that in hand, I can get the contents of my “to-read” shelf with code>GetShelfrunar, to-read/code>, where code>runar/code> is my Goodreads user id. And given that, I can call code>RunarRank/code> on each book on the shelf, then sort the result by that rank:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>RunarSort/span>span classp>/span>span classnv>shelf_/span>span classp>/span>span classw> /span>span classo>:/span>span classw>/span>/span>span classline>span classw> /span>span classn>Sort/span>span classp>/span>span classn>Map/span>span classp>/span>span classn>Function/span>span classp>/span>span classn>x/span>span classp>,/span>span classw> /span>span classn>Append/span>span classp>/span>span classn>x/span>span classp>,/span>span classw> /span>span classs>"rank"/span>span classw> /span>span classo>->/span>span classw> /span>span classn>RunarRank/span>span classp>/span>span classn>x/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classn>shelf/span>span classp>,/span>span classw> /span>span classnv>#1/span>span classp>/span>span classs>"rank"/span>span classp>/span>span classw> /span>span classerr>>/span>span classw> /span>span classnv>#2/span>span classp>/span>span classs>"rank"/span>span classp>/span>span classw> /span>span classo>&/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>To get the ranked reading list of any user:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>ReadingList/span>span classp>/span>span classnv>user_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>span classn>RunarSort/span>span classp>/span>span classn>GetShelf/span>span classp>/span>span classn>user/span>span classp>,/span>span classw> /span>span classs>"to-read"/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And to print it out nicely:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Gridify/span>span classp>/span>span classnv>books_/span>span classp>/span>span classw> /span>span classo>:/span>span classw> /span>/span>span classline>span classw> /span>span classn>Grid/span>span classp>/span>span classn>Flatten/span>span classp>/span>span classw>/span>/span>span classline>span classw> /span>span classn>Cases/span>span classp>/span>span classn>books/span>span classp>,/span>span classw> /span>/span>span classline>span classw> /span>span classnv>b_/span>span classw> /span>span classo>->/span>span classw> /span>span classp>{/span>span classw>/span>/span>span classline>span classw> /span>span classp>{/span>span classn>b/span>span classp>/span>span classs>"id"/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"title"/span>span classp>,/span>span classw> /span>span classn>UnitConvert/span>span classp>/span>span classn>b/span>span classp>/span>span classs>"rank"/span>span classp>,/span>span classw> /span>span classs>"Percent"/span>span classp>},/span>span classw>/span>/span>span classline>span classw> /span>span classp>{/span>span classs>""/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"author"/span>span classp>,/span>span classw> /span>span classn>b/span>span classp>/span>span classs>"avg"/span>span classp>},/span>span classw> /span>span classp>{/span>span classs>""/span>span classp>,/span>span classw> /span>span classs>""/span>span classp>,/span>span classw> /span>span classs>""/span>span classp>}/span>span classw> /span>span classp>},/span>span classw> /span>span classmi>1/span>span classp>,/span>span classw>/span>/span>span classline>span classw> /span>span classn>Alignment/span>span classw> /span>span classo>->/span>span classw> /span>span classn>Left/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now I can get, say, the first 10 books on my improved reading list:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classmathematica>span classline>span classn>Gridify/span>span classp>/span>span classn>ReadingList/span>span classp>/span>span classn>runar/span>span classp>/span>span classmi>1/span>span classw> /span>span classo>;;/span>span classw> /span>span classmi>10/span>span classp>/span>span classw>/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>table>thead>tr>th styletext-align:left;> /th>th styletext-align:left;> /th>th styletext-align:right;> /th>/tr>/thead>tbody>tr>td styletext-align:left;> 9934419 /td>td styletext-align:left;> Kvæðasafn /td>td styletext-align:right;> 75.2743% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Snorri Hjartarson /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 17278 /td>td styletext-align:left;> The Feynman Lectures on Physics Vol 1 /td>td styletext-align:right;> 67.2231% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Richard P. Feynman /td>td styletext-align:right;> 4.58 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 640909 /td>td styletext-align:left;> The Knowing Animal: A Philosophical Inquiry Into Knowledge and Truth /td>td styletext-align:right;> 64.6221% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Raymond Tallis /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 640913 /td>td styletext-align:left;> The Hand: A Philosophical Inquiry Into Human Being /td>td styletext-align:right;> 64.6221% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Raymond Tallis /td>td styletext-align:right;> 5.00 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 4050770 /td>td styletext-align:left;> Volition As Cognitive Self Regulation /td>td styletext-align:right;> 62.231% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Harry Binswanger /td>td styletext-align:right;> 4.86 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 8664353 /td>td styletext-align:left;> Unbroken: A World War II Story of Survival, Resilience, and Redemption /td>td styletext-align:right;> 60.9849% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Laura Hillenbrand /td>td styletext-align:right;> 4.45 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 13413455 /td>td styletext-align:left;> Software Foundations /td>td styletext-align:right;> 60.1596% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Benjamin C. Pierce /td>td styletext-align:right;> 4.80 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 77523 /td>td styletext-align:left;> Harry Potter and the Sorcerer’s Stone (Harry Potter #1) /td>td styletext-align:right;> 59.1459% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> J.K. Rowling /td>td styletext-align:right;> 4.39 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 13539024 /td>td styletext-align:left;> Free Market Revolution: How Ayn Rand’s Ideas Can End Big Government /td>td styletext-align:right;> 59.1102% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Yaron Brook /td>td styletext-align:right;> 4.48 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;> 1609224 /td>td styletext-align:left;> The Law /td>td styletext-align:right;> 58.767% /td>/tr>tr>td styletext-align:left;> /td>td styletext-align:left;> Frédéric Bastiat /td>td styletext-align:right;> 4.40 /td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>/tbody>/table>p>I’m quite happy with that. Some very popular and well-loved books interspersed with obscure ones with exclusively (or almost exclusively) positive reviews. The most satisfying thing is that the rating carries a real meaning. It’s basically the relative likelihood that I will enjoy the book enough to rate it five stars./p>p>I can test this ranking against books I’ve already read. Here’s the top of my “read” shelf, according to their Rúnar Rank:/p>table>thead>tr>th styletext-align:left;> /th>th styletext-align:left;> /th>th styletext-align:right;> /th>/tr>/thead>tbody>tr>td styletext-align:left;>17930467/td>td styletext-align:left;>The Fourth Phase of Water/td>td styletext-align:right;>68.0406%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Gerald H. Pollack/td>td styletext-align:right;>4.85/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>7687279/td>td styletext-align:left;>Nothing Less Than Victory: Decisive Wars and the Lessons of History/td>td styletext-align:right;>64.9297%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>John David Lewis/td>td styletext-align:right;>4.67/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>43713/td>td styletext-align:left;>Structure and Interpretation of Computer Programs/td>td styletext-align:right;>62.0211%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Harold Abelson/td>td styletext-align:right;>4.47/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>7543507/td>td styletext-align:left;>Capitalism Unbound: The Incontestable Moral Case for Individual Rights/td>td styletext-align:right;>57.6085%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Andrew Bernstein/td>td styletext-align:right;>4.67/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>13542387/td>td styletext-align:left;>The DIM Hypothesis: Why the Lights of the West Are Going Out/td>td styletext-align:right;>55.3296%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Leonard Peikoff/td>td styletext-align:right;>4.37/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>5932/td>td styletext-align:left;>Twenty Love Poems and a Song of Despair/td>td styletext-align:right;>54.7205%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Pablo Neruda/td>td styletext-align:right;>4.36/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>18007564/td>td styletext-align:left;>The Martian/td>td styletext-align:right;>53.9136%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Andy Weir/td>td styletext-align:right;>4.36/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>24113/td>td styletext-align:left;>Gödel, Escher, Bach: An Eternal Golden Braid/td>td styletext-align:right;>53.5588%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Douglas R. Hofstadter/td>td styletext-align:right;>4.29/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>19312/td>td styletext-align:left;>The Brothers Lionheart/td>td styletext-align:right;>53.0952%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Astrid Lindgren/td>td styletext-align:right;>4.33/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>tr>td styletext-align:left;>13541678/td>td styletext-align:left;>Functional Programming in Scala/td>td styletext-align:right;>52.6902%/td>/tr>tr>td styletext-align:left;>/td>td styletext-align:left;>Rúnar Bjarnason/td>td styletext-align:right;>4.54/td>/tr>tr>td styletext-align:left;> /td>td>/td>td>/td>/tr>/tbody>/table>p>That’s perfect. Those are definitely books I thouroughly enjoyed and would heartily recommend. Especially that last one./p>p>I’ve published this function as a Wolfram Cloud API, and you can call it at a hrefhttps://www.wolframcloud.com/app/objects/4f4a7b3c-38a5-4bf3-81b6-7ca8e05ea100>https://www.wolframcloud.com/app/objects/4f4a7b3c-38a5-4bf3-81b6-7ca8e05ea100/a>. It takes two URL query parameters, code>key/code> and code>user/code>, which are your Goodreads API key and the Goodreads user ID whose reading list you want to generate, respectively. Enjoy!/p>/div> /article> article> header> h1 classentry-title>a href/blog/2014/12/21/maximally-powerful/>Maximally Powerful, Minimally Useful/a>/h1> p classmeta> time classentry-date datetime2014-12-21T23:23:00-05:00>span classdate>span classdate-month>Dec/span> span classdate-day>21/span>span classdate-suffix>st/span>, span classdate-year>2014/span>/span> span classtime>11:23 pm/span>/time> /p> /header> div classentry-content>p>It’s well known that there is a trade-off in language and systems design between expressiveness and analyzability. That is, the more expressive a language or system is, the less we can reason about it, and vice versa. The more capable the system, the less comprehensible it is./p>p>This principle is very widely applicable, and it’s a useful thing to keep in mind when designing languages and libraries. A practical implication of being aware of this principle is that we always make components exactly as expressive as necessary, but no more. This maximizes the ability of any downstream systems to reason about our components. And dually, for things that we receive or consume, we should require exactly as much analytic power as necessary, and no more. That maximizes the expressive freedom of the upstream components./p>p>I find myself thinking about this principle a lot lately, and seeing it more or less everywhere I look. So I’m seeking a more general statement of it, if such a thing is possible. It seems that more generally than issues of expressivity/analyzability, a restriction at one semantic level translates to freedom and power at another semantic level./p>p>What I want to do here is give a whole bunch of examples. Then we’ll see if we can come up with an integration for them all. This is all written as an exercise in thinking out loud and is not to be taken very seriously./p>h2>Examples from computer science/h2>h3>Context-free and regular grammars/h3>p>In formal language theory, context-free grammars are more expressive than regular grammars. The former can describe strictly more sets of strings than the latter. On the other hand, it’s harder to reason about context-free grammars than regular ones. For example, we can decide whether two regular expressions are equal (they describe the same set of strings), but this is undecidable in general for context-free grammars./p>h3>Monads and applicative functors/h3>p>If we know that an applicative functor is a monad, we gain some expressive power that we don’t get with just an applicative functor. Namely, a monad is an applicative functor with an additional capability: monadic join (or “bind”, or “flatMap”). That is, context-sensitivity, or the ability to bind variables in monadic expressions./p>p>This power comes at a cost. Whereas we can always compose any two applicatives to form a composite applicative, two monads do not in general compose to form a monad. It may be the case that a given monad composes with any other monad, but we need some additional information about it in order to be able to conclude that it does./p>h3>Actors and futures/h3>p>Futures have an algebraic theory, so we can reason about them algebraically. Namely, they form an applicative functor which means that two futures code>x/code> and code>y/code> make a composite future that does code>x/code> and code>y/code> in parallel. They also compose sequentially since they form a monad./p>p>Actors on the other hand have no algebraic theory and afford no algebraic reasoning of this sort. They are “fire and forget”, so they could potentially do anything at all. This means that actor systems can do strictly more things in more ways than systems composed of futures, but our ability to reason about such systems is drastically diminished./p>h3>Typed and untyped programming/h3>p>When we have an untyped function, it could receive any type of argument and produce any type of output. The implementation is totally unrestricted, so that gives us a great deal of expressive freedom. Such a function can potentially participate in a lot of different expressions that use the function in different ways./p>p>A function of type code>Bool -> Bool/code> however is highly restricted. Its argument can only be one of two things, and the result can only be one of two things as well. So there are 4 different implementations such a function could possibly have. Therefore this restriction gives us a great deal of analyzability./p>p>For example, since the argument is of type code>Bool/code> and not code>Any/code>, the implementation mostly writes itself. We need to consider only two possibilities. code>Bool/code> (a type of size 2) is fundamentally easier to reason about than code>Any/code> (a type of potentially infinite size). Similarly, any usage of the function is easy to reason about. A caller can be sure not to call it with arguments other than code>True/code> or code>False/code>, and enlist the help of a type system to guarantee that expressions involving the function are meaningful./p>h3>Total functional programming/h3>p>Programming in non-total languages affords us the power of general recursion and “fast and loose reasoning” where we can transition between valid states through potentially invalid ones. The cost is, of course, the halting problem. But more than that, we can no longer be certain that our programs are em>meaningful/em>, and we lose some algebraic reasoning. For example, consider the following:/p>figure classcode>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code class>span classline>map (- n) (map (+ n) xs)) xs/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This states that adding code>n/code> to every number in a list and then subtracting code>n/code> again should be the identity. But what if code>n/code> actually throws an exception or never halts? In a non-total language, we need some additional information. Namely, we need to know that code>n/code> is total./p>h3>Referential transparency and side effects/h3>p>The example above also serves to illustrate the trade-off between purely functional and impure programming. If code>n/code> could have arbitrary side effects, algebraic reasoning of this sort involving code>n/code> is totally annihilated. But if we know that code>n/code> is referentially transparent, algebraic reasoning is preserved. The power of side effects comes at the cost of algebraic reasoning. This price includes loss of compositionality, modularity, parallelizability, and parametricity. Our programs can do strictly more things, but we can conclude strictly fewer things about our programs./p>h2>Example from infosec/h2>p>There is a principle in computer security called em>The Principle of Least Privilege/em>. It says that a user or program should have exactly as much authority as necessary but no more. This constrains the power of the entity, but greatly enhances the power of others to predict and reason about what the entity is going to do, resulting in the following benefits:/p>ul>li>strong>Compositionality/strong> – The fewer privileges a component requires, the easier it is to deploy inside a larger environment. For the purposes of safety, higher privileges are a barrier to composition since a composite system requires the em>highest/em> privileges of any of its components./li>li>strong>Modularity/strong> – A component with restricted privileges is easier to reason about in the sense that its interaction with other components will be limited. We can reason mechanically about where this limit actually is, which gives us better guarantees about the the security and stability of the overall system. A restricted component is also easier to test in isolation, since it can be run inside an overall restricted environment./li>/ul>h2>Example from politics/h2>p>Some might notice an analogy between the Principle of Least Privilege and the idea of a constitutionally limited government. An absolute dictatorship or pure democracy will have absolute power to enact whatever whim strikes the ruler or majority at the moment. But the overall stability, security, and freedom of the people is greatly enhanced by the presence of legal limits on the power of the government. A limited constitutional republic also makes for a better neighbor to other states./p>p>More generally, a ban on the initiation of physical force by one citizen against another, or by the government against citizens, or against other states, makes for a peaceful and prosperous society. The “cost” of such a system is the inability of one person (or even a great number of people) to impose their preferences on others by force./p>h2>An example from mathematics/h2>p>The framework of two-dimensional Euclidean geometry is simply an empty page on which we can construct lines and curves using tools like a compass and straightedge. When we go from that framework to a Cartesian one, we constrain ourselves to reasoning on a grid of pairs of numbers. This is a tradeoff between expressivity and analyzability. When we move fom Euclidean to Cartesian geometry, we lose the ability to assume isotropy of space, intersection of curves, and compatibility between dimensions. But we gain much more powerful things through the restriction: the ability to precisely define geometric objects, to do arithmetic with them, to generalize to higher dimensions, and to reason with higher abstractions like linear algebra and category theory./p>h2>Examples from everyday life/h2>h3>Driving on roads/h3>p>Roads constrain the routes we can take when we drive or walk. We give up moving in a straight line to wherever we want to go. But the benefit is huge. Roads let us get to where we’re going much faster and more safely than we would otherwise./p>h3>Commodity components/h3>p>Let’s say you make a decision to have only one kind of outfit that you wear on a daily basis. You just go out and buy multiple identical outfits. Whereas you have lost the ability to express yourself by the things you wear, you have gained a certain ability to reason about your clothing. The system is also fault-tolerant and compositional!/p>h2>Summary/h2>p>What is this principle? Here are some ways of saying it:/p>ul>li>Things that are maximally general for first-order applications are minimally useful for higher-order applications, and vice versa./li>li>A language that is maximally expressive is minimally analyzable./li>li>A simplifying assumption at one semantic level paves the way to a richer structure at a higher semantic level./li>/ul>p>What do you think? Can you think of a way to integrate these examples into a general principle? Do you have other favorite examples of this principle in action? Is this something everyone already knows about and I’m just late to the party?/p>/div> /article> div classpagination> a classprev href/posts/2>← Older/a> a href/blog/archives>Blog Archives/a> /div>/div>aside classsidebar> section>h1>Read my book/h1>a hrefhttp://manning.com/bjarnason>img src/images/FPinScalaCover.png width553px height694px>/a>/section>section> h1>Recent Posts/h1> ul idrecent_posts> li classpost> a href/blog/2016/04/02/a-comonad-of-graph-decompositions/>A Comonad of Graph Decompositions/a> /li> li classpost> a href/blog/2015/10/12/freedom-and-forgetfulness/>Freedom and Forgetfulness/a> /li> li classpost> a href/blog/2015/10/04/scala-comonad-tutorial-part-2/>Scala Comonad Tutorial, Part 2/a> /li> li classpost> a href/blog/2015/09/30/the-adjunction-that-induces-the-reader-monad/>An Adjunction That Induces the Reader Monad/a> /li> li classpost> a href/blog/2015/06/23/a-scala-comonad-tutorial/>A Scala Comonad Tutorial, Part 1/a> /li> /ul>/section>section> h1>GitHub Repos/h1> ul idgh_repos> li classloading>Status updating…/li> /ul> a hrefhttps://github.com/runarorama>@runarorama/a> on GitHub script typetext/javascript> $(document).ready(function(){ if (!window.jXHR){ var jxhr document.createElement(script); jxhr.type text/javascript; jxhr.src /javascripts/libs/jXHR.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(jxhr, s); } github.showRepos({ user: runarorama, count: 4, skip_forks: false, target: #gh_repos }); }); /script> script src/javascripts/github.js typetext/javascript> /script>/section> /aside> /div> /div> footer rolecontentinfo>p> Copyright © 2018 - Rúnar Bjarnason - span classcredit>Powered by a hrefhttp://octopress.org>Octopress/a>/span>/p>/footer> div idfb-root>/div>script>(function(d, s, id) { var js, fjs d.getElementsByTagName(s)0; if (d.getElementById(id)) {return;} js d.createElement(s); js.id id; js.async true; js.src //connect.facebook.net/en_US/all.js#appId212934732101925&xfbml1; fjs.parentNode.insertBefore(js, fjs);}(document, script, facebook-jssdk));/script> script typetext/javascript> (function() { var script document.createElement(script); script.type text/javascript; script.async true; script.src https://apis.google.com/js/plusone.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(script, s); })(); /script> script typetext/javascript> (function(){ var twitterWidgets document.createElement(script); twitterWidgets.type text/javascript; twitterWidgets.async true; twitterWidgets.src //platform.twitter.com/widgets.js; document.getElementsByTagName(head)0.appendChild(twitterWidgets); })(); /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]