{"id":32,"date":"2015-02-16T08:25:00","date_gmt":"2015-02-15T22:25:00","guid":{"rendered":""},"modified":"2018-05-22T20:51:48","modified_gmt":"2018-05-22T10:51:48","slug":"monad-thats-a-wrap","status":"publish","type":"post","link":"https:\/\/pbw.id.au\/blog\/2015\/02\/monad-thats-a-wrap\/","title":{"rendered":"Monad; that&#8217;s a wrap!"},"content":{"rendered":"<p>Just like everybody else who starts to look at monads, I found it was like coming to the face of a sheer cliff. \u00a0Let me qualify that: just like every other programmer who is not a mathematician (and that&#8217;s most of us). \u00a0I am looking at monads in the context of clojure, so code snippets will generally be written in clojure-like syntax.<\/p>\n<p>I have found these resources the most helpful:<\/p>\n<div><\/div>\n<ul>\n<li>Adam Smyczek&#8217;s\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=ObR3qi4Guys\">Introduction to Monads<\/a>\u00a0on YouTube<\/li>\n<li>Santosh Rajan&#8217;s\u00a0blog\u00a0<a href=\"http:\/\/functionaljavascript.blogspot.in\/2013\/07\/monads.html\">Functional JavaScript<\/a><\/li>\n<li>Jim Duey&#8217;s <a href=\"http:\/\/www.clojure.net\/2012\/02\/02\/Monads-in-Clojure\/\">discussion of monads<\/a> on his blog about Clojure<\/li>\n<\/ul>\n<p><!--more-->Adam&#8217;s talk eschews category theory, and mathematics in general, concentrating on how to define and use monads in code. \u00a0This is an essential approach for <i>the rest of us<\/i>. Unfortunately, all of the terms used in discussing monads hark back to the mathematics, and that, I believe, makes the practical use of monads more confusing than it need be. \u00a0This point was brought home to me strongly when, after observing what some of the others were saying, I watched the first part of a lecture by <a href=\"https:\/\/www.youtube.com\/watch?v=9fohXBj2UEI\">this extraordinary woman<\/a>.<\/p>\n<p><span style=\"font-size: large;\"><b style=\"background-color: white;\"><span style=\"color: red;\">Warning<\/span><\/b>:<\/span> take everything I say with a large grain of salt. \u00a0I am writing this to help me to sort it out in my own mind, and there are no guarantees that any of it is correct.<\/p>\n<p>In all of the discussions I have seen, it is stressed that monads are defined in terms of the behaviour of two functions.<\/p>\n<h3><b><span style=\"font-family: Courier New, Courier, monospace; font-size: large;\">wrap<\/span><\/b><\/h3>\n<p>Although it is not usually mentioned first, I will start with the function that I will call <b><span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span><\/b>. \u00a0Nobody else calls it that, but that&#8217;s what it does. It goes by a number of aliases:<\/p>\n<ul>\n<li><span style=\"font-family: Courier New, Courier, monospace;\">result<\/span>, <span style=\"font-family: Courier New, Courier, monospace;\">m_result<\/span>, <span style=\"font-family: Courier New, Courier, monospace;\">mResult<\/span>, etc.<\/li>\n<li><span style=\"font-family: Courier New, Courier, monospace;\">return<\/span>, <span style=\"font-family: Courier New, Courier, monospace;\">m_return<\/span>, etc.<\/li>\n<li><span style=\"font-family: Courier New, Courier, monospace;\">lift<\/span>, <span style=\"font-family: Courier New, Courier, monospace;\">m_lift<\/span>, etc.<\/li>\n<li>the monadic function (? Sometimes. However, the 2nd argument to <span style=\"font-family: Courier New, Courier, monospace;\">rewrap\u00a0<\/span>\u2014see below\u2014 is generally called <i>monadic function<\/i>, so it may be more accurate to describe <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span> as the base function on which all other monadic functions of a given monad are built.)<\/li>\n<\/ul>\n<div>When he discusses the Array Monad for Javascript, Santosh Rajan gives the following signature for <i>the monadic function<\/i>, i.e. <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span>.<\/div>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">f: T -&gt; [T]<\/span><\/p><\/blockquote>\n<p>That is, for the Array Monad, <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span> takes a value of some type <span style=\"font-family: Courier New, Courier, monospace;\">T<\/span>, and <i>wraps<\/i> it in an array. \u00a0Both the type of value and the mode of wrapping are specific to each defined monad, but once defined, they are fixed for that monad.<\/p>\n<p>The resulting, wrapped, value returned from <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span> is known as a <i><b>monadic value<\/b><\/i>, and is often represented in code as <span style=\"font-family: Courier New, Courier, monospace;\"><b>mv<\/b><\/span>. \u00a0In this discussion, I&#8217;ll call it <span style=\"font-family: Courier New, Courier, monospace;\"><b>wrapt<\/b><\/span>, for obvious reasons. I&#8217;ll call the argument to <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span> the <span style=\"font-family: Times, Times New Roman, serif;\"><i>basic value<\/i><\/span>, or <span style=\"font-family: Courier New, Courier, monospace;\"><b>bv<\/b><\/span>.<\/p>\n<blockquote>\n<pre><span style=\"font-family: Courier New, Courier, monospace;\">;; Takes a basic value; returns a wrapt value\n<\/span><span style=\"font-family: Courier New, Courier, monospace;\">(defn mymonad-wrap [bv]<\/span>\n<span style=\"font-family: Courier New, Courier, monospace;\">  (let [wrapt (<\/span><span style=\"font-family: Times, Times New Roman, serif;\"><i>do-the-wrapping-of<\/i><\/span><span style=\"font-family: Courier New, Courier, monospace;\"> bv)]\n    wrapt))<\/span><\/pre>\n<\/blockquote>\n<p>You can see why <i>monadic values<\/i> are frequently called <i><b>containers<\/b><\/i>.<\/p>\n<h3><span style=\"color: #999999; font-family: Courier New, Courier, monospace; font-size: large;\"><b>(unwrap)<\/b><\/span><\/h3>\n<p><span style=\"font-family: Courier New, Courier, monospace;\">unwrap<\/span> is under wraps, so to speak, because it is not part of the public face of monads. <i>It is <b>NOT<\/b> one of the two functions which define the behaviour of a monad<\/i>. \u00a0It is, however, essential to the functioning of monads, and some kind of <span style=\"font-family: Courier New, Courier, monospace;\">unwrap<\/span> functionality must be available to the other function in the definition of monad:\u00a0<span style=\"font-family: Courier New, Courier, monospace;\">rewrap<\/span>.<\/p>\n<p><span style=\"font-family: Courier New, Courier, monospace;\">unwrap<\/span> is the inverse of <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span>, not surprisingly. \u00a0In terms of Santosh&#8217;s Array monad, it&#8217;s signature might look like this.<\/p>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">f: T &lt;- [T]<\/span><\/p><\/blockquote>\n<p>That is, unwrap takes a <i><span style=\"font-family: Courier New, Courier, monospace;\">wrapt<\/span> (monadic value)<\/i>, which is a wrapped <i>basic value<\/i> and returns the <i>basic value<\/i>.<\/p>\n<h3><span style=\"font-family: Courier New, Courier, monospace; font-size: large;\"><b>rewrap<\/b><\/span><\/h3>\n<p>This the function that is generally called <span style=\"font-family: Courier New, Courier, monospace;\">bind<\/span>, <span style=\"font-family: Courier New, Courier, monospace;\">m_bind<\/span>, etc., although in Santosh&#8217;s examples, this function takes the name of the monad; for example, <span style=\"font-family: Courier New, Courier, monospace;\">arrayMonad<\/span>. \u00a0The signature that Santosh gives for this function in the Array Monad is<\/p>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">M: [T] -&gt; [T]<\/span><\/p><\/blockquote>\n<p>That is, it transforms a <i><span style=\"font-family: Courier New, Courier, monospace;\">wrapt<\/span>\u00a0value<\/i> to another\u00a0<i><span style=\"font-family: Courier New, Courier, monospace;\">wrapt<\/span>\u00a0value<\/i>. In the case of the Array monad, the basic value is wrapped in an array.<\/p>\n<p><span style=\"font-family: Courier New, Courier, monospace;\">rewrap<\/span> looks like this.<\/p>\n<blockquote>\n<pre><span style=\"font-family: Courier New, Courier, monospace;\">(defn mymonad-rewrap [wrapt, mf]\n  ;; call monadic function given as 2nd arg, on the\n  ;; basic value extracted from the wrapt value given\n  ;; in the 1st argument. Return the new wrapt value.\n  (let [bv (<\/span><span style=\"font-family: Times, Times New Roman, serif;\">do-unwrap-fn-on<\/span><span style=\"font-family: Courier New, Courier, monospace;\"> wrapt)\n        new-wrapt (mf bv)]\n    new-wrapt))<\/span><\/pre>\n<\/blockquote>\n<p>So, what <span style=\"font-family: Courier New, Courier, monospace;\">rewrap<\/span> does is<\/p>\n<div>\n<ul>\n<li><span style=\"font-family: Courier New, Courier, monospace;\">unwrap<\/span> its <i>monadic value<\/i> argument to get the <i>basic value<\/i><\/li>\n<li>call its <i>monadic function<\/i> argument with the unwrapped <i>basic value<\/i>\u00a0to&#8230;\n<ul>\n<li>modify the <i>basic value<\/i><\/li>\n<li><span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span>\u00a0the modified\u00a0<i>basic value\u00a0<\/i>and return a new <i><span style=\"font-family: Courier New, Courier, monospace;\">wrapt<\/span> value<\/i><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/div>\n<p>The <i>monadic function<\/i> argument, <span style=\"font-family: Courier New, Courier, monospace;\">mf<\/span>, deserves a closer look. \u00a0<span style=\"font-family: Courier New, Courier, monospace;\">mf<\/span> operates on a <i>basic value<\/i> to produce a new <span style=\"font-family: Courier New, Courier, monospace;\">wrapt<\/span> value. \u00a0It is, in fact, a composition of functions. \u00a0It composes <span style=\"font-family: Courier New, Courier, monospace;\">wrap<\/span><span style=\"font-family: Times, Times New Roman, serif;\">\u00a0and some operation that modifies the <i>basic value<\/i>. \u00a0So,<\/span><\/p>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">mf \u21d2 (<\/span><span style=\"font-family: Courier New, Courier, monospace;\">f\u2032\u00a0<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">\u22c5 wrap<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">)<\/span><\/p><\/blockquote>\n<p>where\u00a0<span style=\"font-family: 'Courier New', Courier, monospace;\">f\u2032<\/span>\u00a0is a function that modifies the <i>basic value<\/i>. In that scheme, wrap itself can be described as<\/p>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">wrap\u2032 \u21d2 (identity\u00a0<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">\u22c5 wrap<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">)<\/span><\/p><\/blockquote>\n<p>That given, we can now describe <span style=\"font-family: Courier New, Courier, monospace;\">rewrap<\/span> as<\/p>\n<blockquote>\n<pre style=\"font-family: 'Courier New', Courier, monospace;\">(defn rewrap [wrapt, <span style=\"white-space: normal;\">(f\u2032\u00a0<\/span>\u22c5 wrap)]<\/pre>\n<pre style=\"font-family: 'Courier New', Courier, monospace;\">  (let [bv (unwrap wrapt)\n        new-wrapt (wrap (f\u2032 bv))]\n    new-wrapt))<\/pre>\n<\/blockquote>\n<p>or, equivalently,<\/p>\n<blockquote>\n<pre style=\"font-family: 'Courier New', Courier, monospace;\">(defn rewrap [wrapt, <span style=\"white-space: normal;\">(f\u2032\u00a0<\/span>\u22c5 wrap)]<\/pre>\n<pre style=\"font-family: 'Courier New', Courier, monospace;\">  (wrap (<span style=\"white-space: normal;\">f\u2032<\/span> (unwrap wrapt))))<\/pre>\n<\/blockquote>\n<h3>The 3 R&#8217;s<\/h3>\n<p>Monads must obey three rules. \u00a0These rules I have taken from <a href=\"http:\/\/www.clojure.net\/2012\/02\/06\/Legalities\/\">Jim Duey&#8217;s post<\/a>, with the appropriate translation to the &#8220;wrap&#8221; terminology I&#8217;m using here.<\/p>\n<h4>Rule 1<\/h4>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">(rewrap (wrap x) f) \u2261 (f x)<\/span><\/p><\/blockquote>\n<p>Alternatively, given our rewriting of <span style=\"font-family: Courier New, Courier, monospace;\">rewrap<\/span>, above, but using\u00a0<span style=\"font-family: 'Courier New', Courier, monospace;\">f<\/span>\u00a0rather than\u00a0<span style=\"font-family: 'Courier New', Courier, monospace;\">(f\u2032\u00a0<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">\u22c5 wrap<\/span><span style=\"font-family: 'Courier New', Courier, monospace;\">)<\/span>;<\/p>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">(f (unwrap (wrap x)) \u2261 (f x)<br \/>\n\u21d2 (f x) \u2261 (f x)<\/span><\/p><\/blockquote>\n<h4>Rule 2<\/h4>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">(rewrap wrapt wrap) \u2261 wrapt<br \/>\n\u21d2 (wrap (unwrap wrapt)) \u2261 wrapt<br \/>\n\u21d2 wrapt \u2261 wrapt<\/span><\/p><\/blockquote>\n<h4>Rule 3<\/h4>\n<blockquote><p><span style=\"font-family: Courier New, Courier, monospace;\">(rewrap (rewrap wrapt f) g) \u2261<br \/>\n(rewrap wrapt (fn [x] (rewrap (f x) g)))<br \/>\nLHS \u21d2 (rewrap (f (unwrap wrapt)) g)<br \/>\n\u21d2 (g (unwrap (f (unwrap wrapt))))<br \/>\n\u21d2 (g (unwrap (f x))) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [1]<br \/>\n\u21d2 (g (unwrap (wrap (f\u2032 x))))<br \/>\n\u21d2 (g (f\u2032 x))<br \/>\nRHS \u21d2 (rewrap wrapt (fn [x] (g (unwrap (f x)))))<br \/>\n\u21d2 ((fn [x] (g (unwrap (f x)))) (unwrap wrapt))<br \/>\n\u21d2 ((fn [x] (g (unwrap (f x)))) x) \u00a0 \u00a0[2]<\/span><\/p><\/blockquote>\n<p>Everything looks pretty straightforward, except for the correspondence between [1] and [2] in Rule 3. Something seems odd about it, even though the results will be the same.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just like everybody else who starts to look at monads, I found it was like coming to the face of a sheer cliff. \u00a0Let me qualify that: just like every other programmer who is not a mathematician (and that&#8217;s most of us). \u00a0I am looking at monads in the context of clojure, so code snippets &hellip; <a href=\"https:\/\/pbw.id.au\/blog\/2015\/02\/monad-thats-a-wrap\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Monad; that&#8217;s a wrap!&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[19],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-code"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8SCfl-w","jetpack-related-posts":[{"id":40,"url":"https:\/\/pbw.id.au\/blog\/2013\/05\/cloning-my-livejournal-blog\/","url_meta":{"origin":32,"position":0},"title":"Cloning my LiveJournal blog","author":"pbw","date":"Fri 3rd May '13","format":false,"excerpt":"I am moving any potentially useful posts over from my LiveJournal blog in hopes that they may be found a little more readily. Most of these posts are from years ago, but some still have relevance.","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/pbw.id.au\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":30,"url":"https:\/\/pbw.id.au\/blog\/2015\/05\/tikadiff-graphical-diff-for-text-from-binary-files\/","url_meta":{"origin":32,"position":1},"title":"tikadiff: graphical diff for text from &#8220;binary&#8221; files","author":"pbw","date":"Sat 9th May '15","format":false,"excerpt":"Code The code is from the Downloads area of my Atlassian Bitbucket repository; see the README online. Version Control Systems (VCSs) VCSs like mercurial, git and bazaar (to mention only a few) are great for keeping track of changes to source files, but their utility doesn't stop there. \u00a0If you're\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/pbw.id.au\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":39,"url":"https:\/\/pbw.id.au\/blog\/2013\/05\/setting-environment-variables-in-os-x-lion\/","url_meta":{"origin":32,"position":2},"title":"Setting Environment Variables in OS X Lion","author":"pbw","date":"Fri 3rd May '13","format":false,"excerpt":"If you want to set environment variables in OS X in such a way as to be recognised in applications run from Finder, it is not enough to set the env var in .profile. \u00a0You must also ensure that the variables are set in the file ~\/.MacOSX\/environment.plist. Setting values in\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/pbw.id.au\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":60,"url":"https:\/\/pbw.id.au\/blog\/2013\/01\/does-intelligent-design-subvert-faith\/","url_meta":{"origin":32,"position":3},"title":"Does Intelligent Design subvert faith?","author":"pbw","date":"Sat 5th Jan '13","format":false,"excerpt":"Spengler (David Goldman) posted an article in the Asia Times Online, titled Why 'Intelligent Design' subverts faith. What follows is my reply. Quotes from Goldman's article are in italics, for the most part. Spengler quotes from an article by David Bentley Hart, hence the reference. The workings of nature are\u2026","rel":"","context":"In &quot;Belief &amp; knowledge&quot;","block_context":{"text":"Belief &amp; knowledge","link":"https:\/\/pbw.id.au\/blog\/category\/belief\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":33,"url":"https:\/\/pbw.id.au\/blog\/2014\/06\/zargrep-grep-files-in-a-zip-archive\/","url_meta":{"origin":32,"position":4},"title":"zargrep: grep files in a zip archive","author":"pbw","date":"Sat 21st Jun '14","format":false,"excerpt":"How do you search for strings within a zip archive? I'm tinkering with EPUB3 files, and I wanted to be able to find certain strings within .epub files, so I had a look around, and I immediately found zgrep and family. The trouble was that zgrep assumes a single zipped\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/pbw.id.au\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":31,"url":"https:\/\/pbw.id.au\/blog\/2015\/03\/help-for-digest-checking\/","url_meta":{"origin":32,"position":5},"title":"Help for digest checking","author":"pbw","date":"Fri 20th Mar '15","format":false,"excerpt":"Updated 2018-02-14 It's pretty important to check the digests of software you download. \u00a0When a downloaded file is accompanied by a signature file, for example a gnupg .asc file, you can verify the signature with various tools. \u00a0Often though, a download site will include the MD5 or SHA1 digest hash\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/pbw.id.au\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/posts\/32","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/comments?post=32"}],"version-history":[{"count":2,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/posts\/32\/revisions"}],"predecessor-version":[{"id":565,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/posts\/32\/revisions\/565"}],"wp:attachment":[{"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/media?parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/categories?post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pbw.id.au\/blog\/wp-json\/wp\/v2\/tags?post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}