|
34 | 34 | <h1>Functors, Applicative Functors and Monoids</h1> |
35 | 35 | <p>Haskell’s combination of purity, higher order functions, parameterized algebraic data types, and typeclasses allows us to implement polymorphism on a much higher level than possible in other languages. We don’t have to think about types belonging to a big hierarchy of types. Instead, we think about what the types can act like and then connect them with the appropriate typeclasses. An <span class="fixed">Int</span> can act like a lot of things. It can act like an equatable thing, like an ordered thing, like an enumerable thing, etc.</p> |
36 | 36 | <p>Typeclasses are open, which means that we can define our own data type, think about what it can act like and connect it with the typeclasses that define its behaviors. Because of that and because of Haskell’s great type system that allows us to know a lot about a function just by knowing its type declaration, we can define typeclasses that define behavior that’s very general and abstract. We’ve met typeclasses that define operations for seeing if two things are equal or comparing two things by some ordering. Those are very abstract and elegant behaviors, but we just don’t think of them as anything very special because we’ve been dealing with them for most of our lives. We recently met functors, which are basically things that can be mapped over. That’s an example of a useful and yet still pretty abstract property that typeclasses can describe. In this chapter, we’ll take a closer look at functors, along with slightly stronger and more useful versions of functors called applicative functors. We’ll also take a look at monoids, which are sort of like socks.</p> |
37 | | -<a name="functors-redux"></a><h2>Functors redux</h2> |
| 37 | +<h2 id="functors-redux">Functors redux</h2> |
38 | 38 | <img src="assets/images/functors-applicative-functors-and-monoids/frogtor.png" alt="frogs dont even need money" class="right" width="369" height="243"> |
39 | 39 | <p>We’ve already talked about functors in <a href="making-our-own-types-and-typeclasses.html#the-functor-typeclass">their own little section</a>. If you haven’t read it yet, you should probably give it a glance right now, or maybe later when you have more time. Or you can just pretend you read it.</p> |
40 | 40 | <p>Still, here’s a quick refresher: Functors are things that can be mapped over, like lists, <span class="fixed">Maybe</span>s, trees, and such. In Haskell, they’re described by the typeclass <span class="fixed">Functor</span>, which has only one typeclass method, namely <span class="fixed">fmap</span>, which has a type of <span class="fixed">fmap :: (a -> b) -> f a -> f b</span>. It says: give me a function that takes an <span class="fixed">a</span> and returns a <span class="fixed">b</span> and a box with an <span class="fixed">a</span> (or several of them) inside it and I’ll give you a box with a <span class="fixed">b</span> (or several of them) inside it. It kind of applies the function to the element inside the box.</p> |
@@ -217,7 +217,7 @@ <h1>Functors, Applicative Functors and Monoids</h1> |
217 | 217 | <p>All the <span class="fixed">Functor</span> instances in the standard library obey these laws, but you can check for yourself if you don’t believe me. And the next time you make a type an instance of <span class="fixed">Functor</span>, take a minute to make sure that it obeys the functor laws. Once you’ve dealt with enough functors, you kind of intuitively see the properties and behaviors that they have in common and it’s not hard to intuitively see if a type obeys the functor laws. But even without the intuition, you can always just go over the implementation line by line and see if the laws hold or try to find a counter-example.</p> |
218 | 218 | <p>We can also look at functors as things that output values in a context. For instance, <span class="fixed">Just 3</span> outputs the value <span class="fixed">3</span> in the context that it might or not output any values at all. <span class="fixed">[1,2,3]</span> outputs three values—<span class="fixed">1</span>, <span class="fixed">2</span>, and <span class="fixed">3</span>, the context is that there may be multiple values or no values. The function <span class="fixed">(+3)</span> will output a value, depending on which parameter it is given.</p> |
219 | 219 | <p>If you think of functors as things that output values, you can think of mapping over functors as attaching a transformation to the output of the functor that changes the value. When we do <span class="fixed">fmap (+3) [1,2,3]</span>, we attach the transformation <span class="fixed">(+3)</span> to the output of <span class="fixed">[1,2,3]</span>, so whenever we look at a number that the list outputs, <span class="fixed">(+3)</span> will be applied to it. Another example is mapping over functions. When we do <span class="fixed">fmap (+3) (*3)</span>, we attach the transformation <span class="fixed">(+3)</span> to the eventual output of <span class="fixed">(*3)</span>. Looking at it this way gives us some intuition as to why using <span class="fixed">fmap</span> on functions is just composition (<span class="fixed">fmap (+3) (*3)</span> equals <span class="fixed">(+3) . (*3)</span>, which equals <span class="fixed">\x -> ((x*3)+3)</span>), because we take a function like <span class="fixed">(*3)</span> then we attach the transformation <span class="fixed">(+3)</span> to its output. The result is still a function, only when we give it a number, it will be multiplied by three and then it will go through the attached transformation where it will be added to three. This is what happens with composition.</p> |
220 | | -<a name="applicative-functors"></a><h2>Applicative functors</h2> |
| 220 | +<h2 id="applicative-functors">Applicative functors</h2> |
221 | 221 | <img src="assets/images/functors-applicative-functors-and-monoids/present.png" class="right" width="302" height="284" alt="disregard this analogy"> |
222 | 222 | <p>In this section, we’ll take a look at applicative functors, which are beefed up functors, represented in Haskell by the <span class="fixed">Applicative</span> typeclass, found in the <span class="fixed">Control.Applicative</span> module.</p> |
223 | 223 | <p>As you know, functions in Haskell are curried by default, which means that a function that seems to take several parameters actually takes just one parameter and returns a function that takes the next parameter and so on. If a function is of type <span class="fixed">a -> b -> c</span>, we usually say that it takes two parameters and returns a <span class="fixed">c</span>, but actually it takes an <span class="fixed">a</span> and returns a function <span class="fixed">b -> c</span>. That’s why we can call a function as <span class="fixed">f x y</span> or as <span class="fixed">(f x) y</span>. This mechanism is what enables us to partially apply functions by just calling them with too few parameters, which results in functions that we can then pass on to other functions.</p> |
@@ -554,7 +554,7 @@ <h1>Functors, Applicative Functors and Monoids</h1> |
554 | 554 | </ul> |
555 | 555 | <p>We won’t go over them in detail right now because that would take up a lot of pages and it would probably be kind of boring, but if you’re up to the task, you can take a closer look at them and see if they hold for some of the instances.</p> |
556 | 556 | <p>In conclusion, applicative functors aren’t just interesting, they’re also useful, because they allow us to combine different computations, such as I/O computations, non-deterministic computations, computations that might have failed, etc. by using the applicative style. Just by using <span class="fixed"><$></span> and <span class="fixed"><*></span> we can use normal functions to uniformly operate on any number of applicative functors and take advantage of the semantics of each one.</p> |
557 | | -<a name="the-newtype-keyword"></a><h2>The newtype keyword</h2> |
| 557 | +<h2 id="the-newtype-keyword">The newtype keyword</h2> |
558 | 558 |
|
559 | 559 | <img src="assets/images/functors-applicative-functors-and-monoids/maoi.png" alt="why_ so serious?" class="left" width="107" height="202"> |
560 | 560 |
|
@@ -1062,7 +1062,7 @@ <h3><span class="fixed">type</span> vs. <span class="fixed">newtype</span> vs. |
1062 | 1062 | keyword. |
1063 | 1063 | </p> |
1064 | 1064 |
|
1065 | | -<a name="monoids"></a><h2>Monoids</h2> |
| 1065 | +<h2 id="monoids">Monoids</h2> |
1066 | 1066 |
|
1067 | 1067 | <img src="assets/images/functors-applicative-functors-and-monoids/pirateship.png" alt="wow this is pretty much the gayest pirate ship |
1068 | 1068 | ever" class="right" width="460" height="417"> |
|
0 commit comments