this repo has no description
1* Monads
2Monads are a natural extension of applicative functors and with them we're concerned with this:
3if you have a value with a context, =m a=, how do you apply to it a function that takes a normal =a= and returns a value with a context?
4That is, how do you apply a function of type =a -> m b= to a value of type =m a=?
5So essentially, we will want this function:
6
7#+begin_src haskell
8(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
9#+end_src
10
11If we have a fancy values and a function that takes a normal value but returns a fancy value, how do we feed that fancy value into the function?
12This is the main question that we will concern ourselves when dealing with monads.
13We write =m a= instead of =f a= because the =m= stands for =Monad=, but monads are just applicative functors that support =>>==. The =>>== function is pronounced as /bind/.
14
15Much to no one's surprise, =Maybe= is a monad, so let's explore it a bit more and see if we can combine it with what we know about monads.
16
17A value of type =Maybe a= represents a value of type =a= with the context of possible failure attached.
18When we looked at =Maybe= as a functor, we saw that if we want to =fmap= a function over it, it gets mapped over the insides if it's a =Just= value, otherwise the =Nothing= is kept because there's nothing to map it over.
19Like this:
20
21#+begin_src haskell
22fmap (++"!") (Just "windom")
23#+end_src
24
25#+RESULTS:
26: Just "windom!"
27
28#+begin_src haskell
29fmap (++"!") Nothing
30#+end_src
31
32#+RESULTS:
33: Nothing
34
35As an applicative functor, it functions simirlaly. However, applicatives also have the function wrapped.
36=Maybe= is an applicative functor in such a way that when we use =<*>= to apply a function inside a =Maybe= to a value that's inside a =Maybe=, they both have to be =Just= values for the result to be a =Just= value, otherwise the result is =Nothing=.
37
38#+begin_src haskell
39Just (+3) <*> Just 3
40#+end_src
41
42#+RESULTS:
43: Just 6
44
45#+begin_src haskell
46Nothing <*> Just "greed"
47#+end_src
48
49#+RESULTS:
50: Nothing
51
52When we use the applicative style to have normal functions act on =Maybe= values, it's similar.
53All the values have to be =Just= values, otherwise it's all for =Nothing=!
54
55#+begin_src haskell
56max <$> Just 3 <*> Just 6
57#+end_src
58
59#+RESULTS:
60: Just 6
61
62#+begin_src haskell
63max <$> Just 3 <*> Nothing
64#+end_src
65
66#+RESULTS:
67: Nothing
68
69And now, let's think about how we would do =>>== for =Maybe=. Like we said, =>>== takes a monadic value, and a function that takes a normal value and returns a monadic value and manages to apply that function to the monadic value.
70How does it do that, if the function takes a normal value? Well, to do that, it has to take into account the context of that monadic value.
71
72In this case, =>>== would take a =Maybe a= value and a function of type =a -> Maybe b= and somehow apply the function to the =Maybe a=.
73To figure out how it does that, we can use the intuition that we have from =Maybe= being an applicative functor.
74Let's say that we have a function =\x -> Just (x+1)=. It takes a number, adds =1= to it and wraps it in a =Just=.
75
76#+begin_src haskell
77(\x -> Just (x+1)) 1
78#+end_src
79
80#+RESULTS:
81: Just 2
82
83Now here's the kicker: how do we feed a =Maybe= value to this function?
84If we think about how =Maybe= acts as an applicative functor, answering this is pretty easy, if we feed it a =Just= value, take what's inside the =Just= and apply the function to it.
85If give it a =Nothing=, then we're left with a function but =Nothing= to apply it to.
86In this case, let's just do what we did before and say that the result is =Nothing=.
87
88Instead of calling it =>>==, let's call it =applyMaybe= for now.
89It takes a =Maybe a= and a function that returns a =Maybe b= and manages to apply that function to the =Maybe a=.
90Here it is in code:
91
92#+begin_src haskell
93 :{
94 applyMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b
95 applyMaybe Nothing f = Nothing
96 applyMaybe (Just x) f = f x
97 :}
98#+end_src
99
100#+RESULTS:
101
102Okay, now let's play with it for a bit.
103We'll use it as an infix function so that the =Maybe= values is on the left side and the function on the right:
104
105#+begin_src haskell
106Just 3 `applyMaybe` \x -> Just (x+1)
107#+end_src
108
109#+RESULTS:
110: Just 4
111
112#+begin_src haskell
113Nothing `applyMaybe` \x -> Just (x+1)
114#+end_src
115
116#+RESULTS:
117: Nothing
118
119In the above example, we see that when we used =applyMaybe= with a =Just= value and a function simply got applied to the value inside the =Just=. When we tried to use it with a =Nothing=, the whole result was =Nothing=.
120What about if the function returns a =Nothing=? Let's see:
121
122#+begin_src haskell
123Just 3 `applyMaybe` \x -> if x > 2 then Just x else Nothing
124#+end_src
125
126#+RESULTS:
127: Just 3
128
129#+begin_src haskell
130Just 1 `applyMaybe` \x -> if x > 2 then Just x else Nothing
131#+end_src
132
133#+RESULTS:
134: Nothing
135
136Just what we expected. If the monadic value on the left is a =Nothing=, the whole thing is =Nothing=.
137And if the function on the right returns a =Nothing=, the result is =Nothing= again.
138This is very similar to when we used =Maybe= as an applicative and we got a =Nothing= result if somewhere in these was a =Nothing=.