Skip to content

Commit 667191e

Browse files
author
Gregory Cox
committed
Change Monad and Alternative definitions to match learnyouahaskell#46, on the current website
1 parent 031c0f9 commit 667191e

File tree

1 file changed

+32
-47
lines changed

1 file changed

+32
-47
lines changed

docs/a-fistful-of-monads.html

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -381,29 +381,22 @@ <h2>The Monad type class</h2>
381381
</p>
382382

383383
<pre name="code" class="haskell:hs">
384-
class Monad m where
384+
class Applicative m =&gt; Monad m where
385385
return :: a -&gt; m a
386+
return = pure
386387

387388
(&gt;&gt;=) :: m a -&gt; (a -&gt; m b) -&gt; m b
388389

389390
(&gt;&gt;) :: m a -&gt; m b -&gt; m b
390391
x &gt;&gt; y = x &gt;&gt;= \_ -&gt; y
391-
392-
fail :: String -&gt; m a
393-
fail msg = error msg
394392
</pre>
395393

396394
<img src="assets/images/a-fistful-of-monads/kid.png" alt="this is you on monads" class="right" width="363" height="451">
397395
<p>
398-
Let's start with the first line. It says <span class="fixed">class Monad m where</span>.
399-
But wait, didn't we say that monads are just beefed up applicative functors? Shouldn't
400-
there be a class constraint in there along the lines of <span
401-
class="fixed">class (Applicative m) = &gt; Monad m where</span> so that a type
402-
has to be an applicative functor first before it can be made a monad? Well,
403-
there should, but when Haskell was made, it hadn't occured to people that
404-
applicative functors are a good fit for Haskell so they weren't in there. But
405-
rest assured, every monad is an applicative functor, even if the <span
406-
class="fixed">Monad</span> class declaration doesn't say so.
396+
Let's start with the first line. It says
397+
<span class="fixed">class (Applicative m) = &gt; Monad m where</span> which means
398+
that if we want to create an instance of Monad for some time, we must have an
399+
instance of Applicative for that type.
407400
</p>
408401

409402
<p>
@@ -445,11 +438,6 @@ <h2>The Monad type class</h2>
445438
instances.
446439
</p>
447440

448-
<p>
449-
The final function of the <span class="fixed">Monad</span> type class is
450-
<span class="fixed">fail</span>. We never use it explicitly in our code. Instead, it's used by Haskell to enable failure in a special syntactic construct for monads that we'll meet later. We don't need to concern ourselves with <span class="fixed">fail</span> too much for now.
451-
</p>
452-
453441
<p>
454442
Now that we know what the <span class="fixed">Monad</span> type class looks
455443
like, let's take a look at how <span class="fixed">Maybe</span> is an instance
@@ -458,17 +446,15 @@ <h2>The Monad type class</h2>
458446

459447
<pre name="code" class="haskell:hs">
460448
instance Monad Maybe where
461-
return x = Just x
462449
Nothing &gt;&gt;= f = Nothing
463450
Just x &gt;&gt;= f = f x
464-
fail _ = Nothing
465451
</pre>
466452

467453
<p>
468-
<span class="fixed">return</span> is the same as <span
469-
class="fixed">pure</span>, so that one's a no-brainer. We do what we did in the
470-
<span class="fixed">Applicative</span> type class and wrap it in a <span
471-
class="fixed">Just</span>.
454+
Both <span class="fixed">return</span> and <span class="fixed">(&gt;&gt;)</span> have <em>default
455+
implementations</em>, so we omit them in instances. <span class="fixed">return</span>
456+
is the same as <span class="fixed">pure</span>, it wraps a value in
457+
<span class="fixed">Just</span>.
472458
</p>
473459

474460
<p>
@@ -1274,25 +1260,26 @@ <h2>do notation</h2>
12741260
present in <span class="fixed">let</span> expressions. When pattern matching
12751261
fails in a <span class="fixed">do</span> expression, the <span
12761262
class="fixed">fail</span> function is called. It's part of the <span
1277-
class="fixed">Monad</span> type class and it enables failed pattern matching to
1263+
class="fixed">MonadFail</span> type class and it enables failed pattern matching to
12781264
result in a failure in the context of the current monad instead of making our
1279-
program crash. Its default implementation is this:
1265+
program crash.
12801266
</p>
12811267

12821268
<pre name="code" class="haskell:hs">
1283-
fail :: (Monad m) =&gt; String -&gt; m a
1284-
fail msg = error msg
1269+
class Monad m =&gt; MonadFail m where
1270+
fail :: String -&gt; m a
12851271
</pre>
12861272

12871273
<p>
1288-
So by default it does make our program crash, but monads that incorporate a
1274+
Monads that incorporate a
12891275
context of possible failure (like <span class="fixed">Maybe</span>) usually
12901276
implement it on their own. For <span class="fixed">Maybe</span>, its implemented
12911277
like so:
12921278
</p>
12931279

12941280
<pre name="code" class="haskell:hs">
1295-
fail _ = Nothing
1281+
instance MonadFail Maybe where
1282+
fail _ = Nothing
12961283
</pre>
12971284

12981285
<p>
@@ -1368,9 +1355,7 @@ <h2>The list monad</h2>
13681355

13691356
<pre name="code" class="haskell:hs">
13701357
instance Monad [] where
1371-
return x = [x]
13721358
xs &gt;&gt;= f = concat (map f xs)
1373-
fail _ = []
13741359
</pre>
13751360

13761361
<p>
@@ -1563,41 +1548,41 @@ <h2>The list monad</h2>
15631548
class="fixed">'7'</span> is part of that string. Pretty clever. To see how
15641549
filtering in list comprehensions translates to the list monad, we have to check
15651550
out the <span class="fixed">guard</span> function and the <span
1566-
class="fixed">MonadPlus</span> type class. The <span class="fixed">MonadPlus</span>
1567-
type class is for monads that can also act as monoids. Here's its definition:
1551+
class="fixed">Alternative</span> type class. The <span class="fixed">Alternative</span>
1552+
type class is for Applicatives that can also act as monoids. Here's its definition:
15681553
</p>
15691554

15701555
<pre name="code" class="haskell:hs">
1571-
class Monad m =&gt; MonadPlus m where
1572-
mzero :: m a
1573-
mplus :: m a -&gt; m a -&gt; m a
1556+
class Applicative f =&gt; Alternative f where
1557+
empty :: f a
1558+
(&lt;|&gt;) :: f a -&gt; f a -&gt; f a
15741559
</pre>
15751560

15761561
<p>
1577-
<span class="fixed">mzero</span> is synonymous to <span class="fixed">mempty</span>
1562+
<span class="fixed">empty</span> is synonymous to <span class="fixed">mempty</span>
15781563
from the <span class="fixed">Monoid</span> type class and <span
1579-
class="fixed">mplus</span> corresponds to <span class="fixed">mappend</span>.
1564+
class="fixed">(&lt;|&gt;)</span> corresponds to <span class="fixed">mappend</span>.
15801565
Because lists are monoids as well as monads, they can be made an instance of
15811566
this type class:
15821567
</p>
15831568

15841569
<pre name="code" class="haskell:hs">
1585-
instance MonadPlus [] where
1586-
mzero = []
1587-
mplus = (++)
1570+
instance Alternative [] where
1571+
empty = []
1572+
(&lt;&gt;) = (++)
15881573
</pre>
15891574

15901575
<p>
1591-
For lists <span class="fixed">mzero</span> represents a non-deterministic
1576+
For lists <span class="fixed">empty</span> represents a non-deterministic
15921577
computation that has no results at all &mdash; a failed computation. <span
1593-
class="fixed">mplus</span> joins two non-deterministic values into one. The
1578+
class="fixed">(&lt;|&gt;)</span> joins two non-deterministic values into one. The
15941579
<span class="fixed">guard</span> function is defined like this:
15951580
</p>
15961581

15971582
<pre name="code" class="haskell:hs">
1598-
guard :: (MonadPlus m) =&gt; Bool -&gt; m ()
1599-
guard True = return ()
1600-
guard False = mzero
1583+
guard :: (Alternative m) =&gt; Bool -&gt; m ()
1584+
guard True = pure ()
1585+
guard False = empty
16011586
</pre>
16021587

16031588
<p>

0 commit comments

Comments
 (0)