{"id":286,"date":"2007-01-23T15:03:40","date_gmt":"2007-01-23T15:03:40","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2007\/01\/23\/haskell-a-first-step-into-monads\/"},"modified":"2007-01-23T15:03:40","modified_gmt":"2007-01-23T15:03:40","slug":"haskell-a-first-step-into-monads","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2007\/01\/23\/haskell-a-first-step-into-monads\/","title":{"rendered":"Haskell: A First Step Into Monads"},"content":{"rendered":"<p> The biggest nightmare for most people learning Haskell is <em>monads<\/em>. Monads are the<br \/>\nkey to how you can implement IO, state, parallelism, and sequencing (among numerous other things) in Haskell. The trick is wrapping your head around them.<\/p>\n<p><!--more--><\/p>\n<p> On the most basic level, they&#8217;re actually pretty easy to understand. Think about something like IO in purely functional terms. When you write a function that performs an IO action, what are you really<br \/>\ndoing in terms of functions? For the moment, ignore all practical concerns, and just think in the<br \/>\npure abstract: what happens when you do an output operation?<\/p>\n<p> What happens is that you write some data to some entity accessible to the program. In purely<br \/>\nfunctional terms, you can think of taking a snapshot of the <em>entire state of stuff accessible to the program<\/em> both before and after the output action. Then the output operation is a function<br \/>\nfrom the state before to the state after. In pseudocode:<\/p>\n<pre>\ndata StateOfEverything = ...\nprint :: String -&gt; StateOfEverything -&gt; StateOfEverything\n<\/pre>\n<p> Now, suppose you want to perform two IO actions in sequence &#8211; like printing &#8220;Hello world&#8221; by printing &#8220;Hello&#8221; and then printing &#8220;world&#8221;. What&#8217;s going on there?<\/p>\n<p> What&#8217;s going on is that you&#8217;re <em>chaining<\/em> functions together, so that the state which<br \/>\nis the output of one function is the input to another.<\/p>\n<pre>\nprintHelloWorld stateBefore =\nlet stateAfter = print \"Hello\" stateBefore\nin print \" World\" stateAfter\n<\/pre>\n<p> Writing things that way &#8211; passing the state returned from one statement as a parameter to<br \/>\nthe next one &#8211; is a pain. It&#8217;s messy, hard to read, and generally unpleasant. So why not just<br \/>\ndo an abstraction? Just write a <em>combinator<\/em>, for chaining together calls. (A<br \/>\ncombinator is a function which takes other functions as parameters for the purpose of combining or modifying them in some way.)<\/p>\n<pre>\nchain :: (x -&gt; x) -&gt; (x -&gt; x) -&gt; x -&gt; x\nchain firstfun secondfun initstate =\nlet nextState = firstfun initstate\nin secondfun nextstate\nprintHello stateBefore =\nprint \"Hello\" stateBefore\nprintWorld stateBefore =\nprint \" World\" stateBefore\nprintHelloWorld stateBefore =\nprintHello `chain` printWorld\n<\/pre>\n<p> That&#8217;s pretty much what a monad does. There&#8217;s a bit more to it &#8211; the combinator needs to behave<br \/>\nin certain ways &#8211; but the central concept is that the monad is a kind of combinator that enables<br \/>\nsequential chaining with the transfer of an internal state object between steps. Haskell also<br \/>\nprovides some nice syntax in the form of &#8220;<code>do<\/code>&#8221; expressions and a ton of flexibility in<br \/>\nterms of monad parameters &#8211; but the most basic thing going on in monad code is that basic chaining of<br \/>\na state parameter from call to call in a sequence.<\/p>\n<p> Now, let&#8217;s look at doing what I just did with &#8220;chain&#8221;, only do it using the Haskell IO monad:<\/p>\n<pre>\n&gt;printHello ::  IO ()\n&gt;printHello  = print \"Hello \"\n&gt;\n&gt;printWorld ::  IO ()\n&gt;printWorld = print \"World\"\n&gt;\n&gt;printHelloWorld ::  IO ()\n&gt;printHelloWorld  = do\n&gt;                      printHello\n&gt;                      printWorld\n<\/pre>\n<p> As you can see, there&#8217;s a <em>monad type<\/em> <code>IO<\/code>, which is an object encapsulating<br \/>\nthe IO state. You <em>can&#8217;t<\/em> see inside of it &#8211; the IO state itself is completely hidden, and<br \/>\ninaccessible to any code outside of the implementation of the IO monad. But what it does is combine<br \/>\nfunctions so that the IO state returned by one operation is passed on to the next in sequence. It&#8217;s really just like the chaining operator &#8211; but with a really nice syntax, and a lot more flexibility. <\/p>\n<p> To see why it&#8217;s more flexible, let&#8217;s start by breaking down the &#8220;<code>do<\/code>&#8221; syntax, and see what&#8217;s really going on. The do statement in the code example above is equivalent to the following:<\/p>\n<pre>\n&gt;printHelloWorldWithoutDo :: IO ()\n&gt;printHelloWorldWithoutDo = printHello &gt;&gt;= ( x -&gt; printWorld)\n<\/pre>\n<p> One of the things that the &#8220;<code>do<\/code>&#8221; syntax does is expand each expression after the<br \/>\nfirst in the do so that the result value of each expression is passed as a parameter to the next. So<br \/>\nin addition to just passing the IO state internally, it also allows the programmer to pass their own<br \/>\nvalue from one element of the sequence to the next. To see just how flexible that is, let&#8217;s take a<br \/>\nmoment, and look at the actually type of &#8220;<code>&gt;&gt;=<\/code>&#8220;.<\/p>\n<pre>\n*Main&gt; :type (&gt;&gt;=)\n(&gt;&gt;=) :: (Monad m) =&gt; m a -&gt; (a -&gt; m b) -&gt; m b\n<\/pre>\n<p> Let&#8217;s piece that apart. First, monads are type-parametric &#8211; meaning that, for example, &#8220;IO&#8221; isn&#8217;t a type; &#8220;IO x&#8221; is a type &#8211; an instance value of the IO monad carrying a <em>payload<\/em> value of type x.<\/p>\n<p> The monadic sequencing parameter takes two parameters. The first is a monad value with a payload of type &#8220;a&#8221;. The second is a function which can be chained with the first &#8211; so it needs to take a parameter value who type is the type of the payload <em>carried over from the first<\/em> &#8211; so it&#8217;s a function from a value of type &#8220;a&#8221; to another monad value &#8211; but <em>it doesn&#8217;t need to return the<br \/>\nsame type as the first<\/em> &#8211; it doesn&#8217;t need to return an instance of <code>IO a<\/code>. It can return whatever type of payload it wants &#8211; so the type of the second parameter is a function from a value of type a, to a monad carrying a value of type b. <\/p>\n<p> What this means is that there&#8217;s a huge amount of flexibility in how we can pass values<br \/>\nbetween steps of a monad! My naive chain operator required everything in a sequence to take and return values of exactly the same type; the actual monadic chaining operator allows each step of a monadic chain to take different types as input, and return different types as output &#8211; so long as the value returned by one step matches the parameter type accepted by the next.<\/p>\n<p> Let&#8217;s take a look at how this value-carrying stuff can actually be really useful &#8211; and at the same time, get a look at the other really wonderful thing about Haskell&#8217;s <code>do<\/code> syntax.<br \/>\nSuppose we want to write the usual follow-on to a hello world program &#8211; that is, a program that<br \/>\nasks for the users name, and then prints out a hello message using it. Here&#8217;s the<br \/>\nprogram as a Python function:<\/p>\n<pre>\ndef FancyHello():\nprint \"What is your name?\"\nx = sys.stdin.readLine()\nprint \"Hello \", x\n<\/pre>\n<p> How do we do that in Haskell?<\/p>\n<pre>\n&gt;fancyHello :: IO ()\n&gt;fancyHello =\n&gt;    do\n&gt;       print \"What is your name?\"\n&gt;       x        print (concat [\"Hello \", x])\n<\/pre>\n<p> In addition to the simple chaining, Haskell <code>do<\/code> statements allow us to <em>bind<\/em><br \/>\nthe payload returned by a step in a monadic sequence to a pattern, and then use the names defined by that pattern throughout the rest of the <code>do<\/code> statement. So, since &#8220;<code>getLine<\/code>&#8221; has type &#8220;<code>IO String<\/code>&#8220;, in the body of a &#8220;<code>do<\/code>&#8221; statement, &#8220;<code>getLine<\/code>&#8221; can be treated as a function that returns a string &#8211; and the result of it can be bound to a variable using the &#8220;<code>&lt;-<\/code>&#8221; operator.<\/p>\n<p> There are a couple of tricks to using monads. Suppose in our <code>fancyHello<\/code> function,<br \/>\nwe wanted to <em>return<\/em> the hello string with the users name, instead of printing it. You <em>might<\/em> think that we could do something easy like:<\/p>\n<pre>\nfancyHW :: String\nfancyHW =\ndo\nprint \"What is your name?\"\nx &lt;- getLine\nconcat [&quot;Hello &quot;, x]\n<\/pre>\n<p> But if you try to put that through a Haskell compiler, you&#8217;ll get a type error. You see, there&#8217;s no way <em>out<\/em> of a monad. Once you&#8217;re inside a monad, there&#8217;s no way out. It&#8217;s a closed world. You <em>can&#8217;t<\/em> get out of it. So you <em>can&#8217;t<\/em> return an input string from the IO monad without the IO state associated with it by the monad. So <code>fancyHW<\/code> can&#8217;t return &#8220;<code>String<\/code>&#8220;; it must return &#8220;<code>IO String<\/code>&#8220;. Based on that, you might think that<br \/>\nthe fix would be to just change the declaration in the code above to:<\/p>\n<pre>\nfancyHW :: IO String\nfancyHW =\ndo\nprint \"What is your name?\"\nx &lt;- getLine\nconcat [&quot;Hello &quot;, x]\n<\/pre>\n<p> Again, it doesn&#8217;t work. <code>concat<\/code> returns a value of type <code>String<\/code>, not<br \/>\na value of type <code>IO String<\/code>. How do we generate a value of type <code>IO String<\/code>? There&#8217;s a function <code>return<\/code>, with type <code>(Monad m) =&gt; a -&gt; m a<\/code>. What <code>return<\/code> does is wrap a non-monadic value into the appropriate monad type, so that it can be used as an element in a monadic sequence.  So let&#8217;s look at the correct version of<br \/>\n&#8220;<code>fancyHW<\/code>&#8220;:<\/p>\n<pre>\n&gt;fancyHW :: IO (String)\n&gt;fancyHW =\n&gt;   do\n&gt;      print \"What is your name?\"\n&gt;      x       return (concat [\"Hello \", x])\n<\/pre>\n<p> This works, but it&#8217;s actually a bit deceptive. In fact, <code>return<\/code> is a bit deceptive &#8211;<br \/>\nit makes monadic code read more clearly in some cases, but it can also be very misleading, because it<br \/>\n<em>does not<\/em> return a value from the &#8220;<code>do<\/code>&#8221; statement; it just wraps a non-monadic<br \/>\ncall, so that it can be enclosed in a monadic sequence. Let&#8217;s look at a variation of the above<br \/>\nto see why it can be confusing. This is a bit artificial to make it short, but it illustrates the point.<\/p>\n<pre>\n&gt;generateHelloMessage :: String -&gt; String\n&gt;generateHelloMessage name = concat [\"Hello there \", name, \", how are you?\"]\n&gt;\n&gt;fancyTwo :: IO ()\n&gt;fancyTwo = do\n&gt;              print \"What is your  name?\"\n&gt;              x               msg               print msg\n<\/pre>\n<p> See, the <code>return<\/code> call isn&#8217;t <em>returning<\/em> a value from the <code>do<\/code> statement, it&#8217;s just wrapping a non-monadic call so that it can be a participant in a<br \/>\nmonadic sequence.<\/p>\n<p> This isn&#8217;t all there is to know about monads; this is just barely scratching the surface. We&#8217;ll go farther with it in the next few posts. We&#8217;ll go through some more details of the IO monad,<br \/>\nshow a couple of other monad types, how to define your own monad types, and show a wonderful example of monads as glue: you can write YACC-like parser code in Haskell without a parser generator,<br \/>\nusing a parser monad!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The biggest nightmare for most people learning Haskell is monads. Monads are the key to how you can implement IO, state, parallelism, and sequencing (among numerous other things) in Haskell. The trick is wrapping your head around them.<\/p>\n","protected":false},"author":1,"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":[89],"tags":[],"class_list":["post-286","post","type-post","status-publish","format-standard","hentry","category-haskell"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-4C","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/286","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=286"}],"version-history":[{"count":1,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/286\/revisions"}],"predecessor-version":[{"id":3578,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/286\/revisions\/3578"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=286"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}