diff --git a/docs/a-fistful-of-monads.html b/docs/a-fistful-of-monads.html index 590b0a5..441984f 100644 --- a/docs/a-fistful-of-monads.html +++ b/docs/a-fistful-of-monads.html @@ -381,29 +381,22 @@

The Monad type class

-class Monad m where
+class Applicative m => Monad m where
     return :: a -> m a
+    return = pure
 
     (>>=) :: m a -> (a -> m b) -> m b
 
     (>>) :: m a -> m b -> m b
     x >> y = x >>= \_ -> y
-
-    fail :: String -> m a
-    fail msg = error msg
 
this is you on monads

-Let's start with the first line. It says class Monad m where. -But wait, didn't we say that monads are just beefed up applicative functors? Shouldn't -there be a class constraint in there along the lines of class (Applicative m) = > Monad m where so that a type -has to be an applicative functor first before it can be made a monad? Well, -there should, but when Haskell was made, it hadn't occurred to people that -applicative functors are a good fit for Haskell so they weren't in there. But -rest assured, every monad is an applicative functor, even if the Monad class declaration doesn't say so. +Let's start with the first line. It says +class (Applicative m) = > Monad m where which means +that if we want to create an instance of Monad for some type, we must have an +instance of Applicative for that type.

@@ -445,11 +438,6 @@

The Monad type class

instances.

-

-The final function of the Monad type class is -fail. 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 fail too much for now. -

-

Now that we know what the Monad type class looks like, let's take a look at how Maybe is an instance @@ -458,17 +446,15 @@

The Monad type class

 instance Monad Maybe where
-    return x = Just x
     Nothing >>= f = Nothing
     Just x >>= f  = f x
-    fail _ = Nothing
 

-return is the same as pure, so that one's a no-brainer. We do what we did in the -Applicative type class and wrap it in a Just. +Both return and (>>) have default +implementations, so we omit them in instances. return +is the same as pure, it wraps a value in +Just.

@@ -1274,25 +1260,26 @@

do notation

present in let expressions. When pattern matching fails in a do expression, the fail function is called. It's part of the Monad type class and it enables failed pattern matching to +class="fixed">MonadFail type class and it enables failed pattern matching to result in a failure in the context of the current monad instead of making our -program crash. Its default implementation is this: +program crash.

-fail :: (Monad m) => String -> m a
-fail msg = error msg
+class Monad m => MonadFail m where
+    fail :: String -> m a
 

-So by default it does make our program crash, but monads that incorporate a +Monads that incorporate a context of possible failure (like Maybe) usually implement it on their own. For Maybe, its implemented like so:

-fail _ = Nothing
+instance MonadFail Maybe where
+    fail _ = Nothing
 

@@ -1368,9 +1355,7 @@

The list monad

 instance Monad [] where
-    return x = [x]
     xs >>= f = concat (map f xs)
-    fail _ = []
 

@@ -1563,41 +1548,41 @@

The list monad

class="fixed">'7' is part of that string. Pretty clever. To see how filtering in list comprehensions translates to the list monad, we have to check out the guard function and the MonadPlus type class. The MonadPlus -type class is for monads that can also act as monoids. Here's its definition: +class="fixed">Alternative type class. The Alternative +type class is for Applicatives that can also act as monoids. Here's its definition:

-class Monad m => MonadPlus m where
-    mzero :: m a
-    mplus :: m a -> m a -> m a
+class Applicative f => Alternative f where
+    empty :: f a
+    (<|>) :: f a -> f a -> f a
 

-mzero is synonymous to mempty +empty is synonymous to mempty from the Monoid type class and mplus corresponds to mappend. +class="fixed">(<|>) corresponds to mappend. Because lists are monoids as well as monads, they can be made an instance of this type class:

-instance MonadPlus [] where
-    mzero = []
-    mplus = (++)
+instance Alternative [] where
+    empty = []
+    (<>) = (++)
 

-For lists mzero represents a non-deterministic +For lists empty represents a non-deterministic computation that has no results at all — a failed computation. mplus joins two non-deterministic values into one. The +class="fixed">(<|>) joins two non-deterministic values into one. The guard function is defined like this:

-guard :: (MonadPlus m) => Bool -> m ()
-guard True = return ()
-guard False = mzero
+guard :: (Alternative m) => Bool -> m ()
+guard True = pure ()
+guard False = empty