Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Allow me to tear down your beliefs about Monads. I sincerely hope you realize that I am not trying to be rude; I'm simply trying to avoid mincing words.</p> <blockquote> <p>A Monad's purpose is to take a function with different input and output types and to make it composable. It does this by wrapping the input and output types with a single monadic type.</p> </blockquote> <p>Not exactly. When you start a sentence with "A Monad's purpose", you're already on the wrong foot. Monads don't necessarily have a "purpose". <code>Monad</code> is simply an abstraction, a classification which applies to certain types and not to others. The purpose of the <code>Monad</code> abstraction is simply that, abstraction.</p> <blockquote> <p>A Monad consists of two interrelated functions: bind and unit.</p> </blockquote> <p>Yes and no. The combination of <code>bind</code> and <code>unit</code> are sufficient to define a Monad, but the combination of <code>join</code>, <code>fmap</code>, and <code>unit</code> are equally sufficient. The latter is, in fact, the way that Monads are typically described in Category Theory.</p> <blockquote> <p>Bind takes a non-composable function f and returns a new function g that accepts the monadic type as input and returns the monadic type.</p> </blockquote> <p>Again, not exactly. A monadic function <code>f :: a -&gt; m b</code> is perfectly composable, with certain types. I can post-compose it with a function <code>g :: m b -&gt; c</code> to get <code>g . f :: a -&gt; c</code>, or I can pre-compose it with a function <code>h :: c -&gt; a</code> to get <code>f . h :: c -&gt; m b</code>.</p> <p>But you got the second part absolutely right: <code>(&gt;&gt;= f) :: m a -&gt; m b</code>. As others have noted, Haskell's <code>bind</code> function takes the arguments in the opposite order.</p> <blockquote> <p>g is composable.</p> </blockquote> <p>Well, yes. If <code>g :: m a -&gt; m b</code>, then you can pre-compose it with a function <code>f :: c -&gt; m a</code> to get <code>g . f :: c -&gt; m b</code>, or you can post-compose it with a function <code>h :: m b -&gt; c</code> to get <code>h . g :: m a -&gt; c</code>. Note that <code>c</code> <em>could</em> be of the form <code>m v</code> where <code>m</code> is a Monad. I suppose when you say "composable" you mean to say "you can compose arbitrarily long chains of functions of this form", which is sort of true.</p> <blockquote> <p>The unit function takes an argument of the type that f expected, and wraps it in the monadic type.</p> </blockquote> <p>A roundabout way of saying it, but yes, that's about right.</p> <blockquote> <p>This [the result of applying <code>unit</code> to some value] can then be passed to g, or to any composition of functions like g.</p> </blockquote> <p>Again, yes. Although it is generally not idiomatic Haskell to call <code>unit</code> (or in Haskell, <code>return</code>) and then pass that to <code>(&gt;&gt;= f)</code>.</p> <pre><code>-- instead of return x &gt;&gt;= f &gt;&gt;= g -- simply go with f x &gt;&gt;= g -- instead of \x -&gt; return x &gt;&gt;= f &gt;&gt;= g -- simply go with f &gt;=&gt; g -- or g &lt;=&lt; f </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COThank you for helping me to understand. But if I have a function `g :: m a -> m b`, why wouldn't I just use `f :: a -> b`? I can't compose g with other functions of like signature. So what are some of the other purposes of monads that would make g more useful than f?
      singulars
    2. COOkay, I might be able to think up a use case to answer my own question: suppose we have a bunch of functions which each take a single value (be it a string, a number, whatever) as input and return a list of values (not necessarily of the same type). If we want to pass the result of a one-to-many function to another one-to-many function, we would normally have to unpack the list returned by the first function, apply the second function to each value, and then concatenate the results. The monad can abstract all of that boilerplate away. Is that a valid example?
      singulars
    3. COOrd: that's a great example, and is precisely the definition of the List instance for Monad. `return x = [x]`; `xs >>= f = concatMap f xs`. (Warning: additional, possibly confusing musings follow) concatMap maps a function `a -> [b]` onto a list of `a`, and then "flattens" the resultant list from `[[b]]` to `[b]`. `concatMap f xs = concat (map f xs)`. This is (not coincidentally) similar to the way `bind` can be defined in terms of `fmap` and `join` for *any* monad: `x >>= f = join (fmap f x)`; you can see that `join = concat` and `fmap = map` for lists.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload