Skip to content

Commit 03982fc

Browse files
author
Gregory Cox
committed
Align use of no-break space U+00A0 and   in markdown and HTML
1 parent 2f45203 commit 03982fc

File tree

6 files changed

+14
-14
lines changed

6 files changed

+14
-14
lines changed

docs/for-a-few-monads-more.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2048,7 +2048,7 @@ <h3>The join function</h3>
20482048

20492049
<p>
20502050
Here’s some food for thought: if the result of one monadic value is another
2051-
monadic value i.e. if one monadic value is nested inside the other, can you
2051+
monadic value i.e. if one monadic value is nested inside the other, can you
20522052
flatten them to just a single normal monadic value? Like, if we have
20532053
<span class="fixed">Just (Just 9)</span>, can we make that into
20542054
<span class="fixed">Just 9</span>? It turns out that any nested monadic value can be

docs/functors-applicative-functors-and-monoids.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ <h1>Functors, Applicative Functors and Monoids</h1>
118118
<p>How does the box analogy hold here? Well, if you stretch it, it holds. When we use <span class="fixed">fmap (+3)</span> over <span class="fixed">Just 3</span>, it’s easy to imagine the <span class="fixed">Maybe</span> as a box that has some contents on which we apply the function <span class="fixed">(+3)</span>. But what about when we’re doing <span class="fixed">fmap (*3) (+100)</span>? Well, you can think of the function <span class="fixed">(+100)</span> as a box that contains its eventual result. Sort of like how an I/O action can be thought of as a box that will go out into the real world and fetch some result. Using <span class="fixed">fmap (*3)</span> on <span class="fixed">(+100)</span> will create another function that acts like <span class="fixed">(+100)</span>, only before producing a result, <span class="fixed">(*3)</span> will be applied to that result. Now we can see how <span class="fixed">fmap</span> acts just like <span class="fixed">.</span> for functions.</p>
119119
<p>The fact that <span class="fixed">fmap</span> is function composition when used on functions isn’t so terribly useful right now, but at least it’s very interesting. It also bends our minds a bit and let us see how things that act more like computations than boxes (<span class="fixed">IO</span> and <span class="fixed">(-&gt;) r</span>) can be functors. The function being mapped over a computation results in the same computation but the result of that computation is modified with the function.</p>
120120
<img src="assets/images/functors-applicative-functors-and-monoids/lifter.png" alt="lifting a function is easier than lifting a million pounds" class="right" width="443" height="450">
121-
<p>Before we go on to the rules that <span class="fixed">fmap</span> should follow, let’s think about the type of <span class="fixed">fmap</span> once more. Its type is <span class="fixed">fmap :: (a -&gt; b) -&gt; f a -&gt; f b</span>. We’re missing the class constraint <span class="fixed">(Functor f) =&gt;</span>, but we left it out here for brevity, because we’re talking about functors anyway so we know what the <span class="fixed">f</span> stands for. When we first learned about <a href="higher-order-functions.html#curried-functions">curried functions</a>, we said that all Haskell functions actually take one parameter. A function <span class="fixed">a -&gt; b -&gt; c</span> actually takes just one parameter of type <span class="fixed">a</span> and then returns a function <span class="fixed">b -&gt; c</span>, which takes one parameter and returns a <span class="fixed">c</span>. That’s how if we call a function with too few parameters (i.e. partially apply it), we get back a function that takes the number of parameters that we left out (if we’re thinking about functions as taking several parameters again). So <span class="fixed">a -&gt; b -&gt; c</span> can be written as <span class="fixed">a -&gt; (b -&gt; c)</span>, to make the currying more apparent.</p>
121+
<p>Before we go on to the rules that <span class="fixed">fmap</span> should follow, let’s think about the type of <span class="fixed">fmap</span> once more. Its type is <span class="fixed">fmap :: (a -&gt; b) -&gt; f a -&gt; f b</span>. We’re missing the class constraint <span class="fixed">(Functor f) =&gt;</span>, but we left it out here for brevity, because we’re talking about functors anyway so we know what the <span class="fixed">f</span> stands for. When we first learned about <a href="higher-order-functions.html#curried-functions">curried functions</a>, we said that all Haskell functions actually take one parameter. A function <span class="fixed">a -&gt; b -&gt; c</span> actually takes just one parameter of type <span class="fixed">a</span> and then returns a function <span class="fixed">b -&gt; c</span>, which takes one parameter and returns a <span class="fixed">c</span>. That’s how if we call a function with too few parameters (i.e. partially apply it), we get back a function that takes the number of parameters that we left out (if we’re thinking about functions as taking several parameters again). So <span class="fixed">a -&gt; b -&gt; c</span> can be written as <span class="fixed">a -&gt; (b -&gt; c)</span>, to make the currying more apparent.</p>
122122
<p>In the same vein, if we write <span class="fixed">fmap :: (a -&gt; b) -&gt; (f a -&gt; f b)</span>, we can think of <span class="fixed">fmap</span> not as a function that takes one function and a functor and returns a functor, but as a function that takes a function and returns a new function that’s just like the old one, only it takes a functor as a parameter and returns a functor as the result. It takes an <span class="fixed">a -&gt; b</span> function and returns a function <span class="fixed">f a -&gt; f b</span>. This is called <i>lifting</i> a function. Let’s play around with that idea by using GHCI’s <span class="fixed">:t</span> command:</p>
123123
<pre name="code" class="haskell:hs">
124124
ghci&gt; :t fmap (*2)
@@ -170,7 +170,7 @@ <h1>Functors, Applicative Functors and Monoids</h1>
170170
<p>Seeing that mapping <span class="fixed">id</span> over a <span class="fixed">Nothing</span> value returns the same value is trivial. So from these two equations in the implementation for <span class="fixed">fmap</span>, we see that the law <span class="fixed">fmap id = id</span> holds.</p>
171171
<img src="assets/images/functors-applicative-functors-and-monoids/justice.png" alt="justice is blind, but so is my dog" class="left" width="345" height="428">
172172
<p><em>The second law says that composing two functions and then mapping the resulting function over a functor should be the same as first mapping one function over the functor and then mapping the other one.</em> Formally written, that means that <span class="label law">fmap (f . g) = fmap f . fmap g</span>. Or to write it in another way, for any functor <i>F</i>, the following should hold: <span class="label law">fmap (f . g) F = fmap f (fmap g F)</span>.</p>
173-
<p>If we can show that some type obeys both functor laws, we can rely on it having the same fundamental behaviors as other functors when it comes to mapping. We can know that when we use <span class="fixed">fmap</span> on it, there won’t be anything other than mapping going on behind the scenes and that it will act like a thing that can be mapped over, i.e. a functor. You figure out how the second law holds for some type by looking at the implementation of <span class="fixed">fmap</span> for that type and then using the method that we used to check if <span class="fixed">Maybe</span> obeys the first law.</p>
173+
<p>If we can show that some type obeys both functor laws, we can rely on it having the same fundamental behaviors as other functors when it comes to mapping. We can know that when we use <span class="fixed">fmap</span> on it, there won’t be anything other than mapping going on behind the scenes and that it will act like a thing that can be mapped over, i.e. a functor. You figure out how the second law holds for some type by looking at the implementation of <span class="fixed">fmap</span> for that type and then using the method that we used to check if <span class="fixed">Maybe</span> obeys the first law.</p>
174174
<p>If you want, we can check out how the second functor law holds for <span class="fixed">Maybe</span>. If we do <span class="fixed">fmap (f . g)</span> over <span class="fixed">Nothing</span>, we get <span class="fixed">Nothing</span>, because doing a <span class="fixed">fmap</span> with any function over <span class="fixed">Nothing</span> returns <span class="fixed">Nothing</span>. If we do <span class="fixed">fmap f (fmap g Nothing)</span>, we get <span class="fixed">Nothing</span>, for the same reason. OK, seeing how the second law holds for <span class="fixed">Maybe</span> if it’s a <span class="fixed">Nothing</span> value is pretty easy, almost trivial. </p><p>How about if it’s a <span class="fixed">Just <i>something</i></span> value? Well, if we do <span class="fixed">fmap (f . g) (Just x)</span>, we see from the implementation that it’s implemented as <span class="fixed">Just ((f . g) x)</span>, which is, of course, <span class="fixed">Just (f (g x))</span>. If we do <span class="fixed">fmap f (fmap g (Just x))</span>, we see from the implementation that <span class="fixed">fmap g (Just x)</span> is <span class="fixed">Just (g x)</span>. Ergo, <span class="fixed">fmap f (fmap g (Just x))</span> equals <span class="fixed">fmap f (Just (g x))</span> and from the implementation we see that this equals <span class="fixed">Just (f (g x))</span>.</p>
175175
<p>If you’re a bit confused by this proof, don’t worry. Be sure that you understand how <a href="higher-order-functions.html#composition">function composition</a> works. Many times, you can intuitively see how these laws hold because the types act like containers or functions. You can also just try them on a bunch of different values of a type and be able to say with some certainty that a type does indeed obey the laws.</p>
176176
<p>Let’s take a look at a pathological example of a type constructor being an instance of the <span class="fixed">Functor</span> typeclass but not really being a functor, because it doesn’t satisfy the laws. Let’s say that we have a type:</p>
@@ -276,7 +276,7 @@ <h1>Functors, Applicative Functors and Monoids</h1>
276276
ghci&gt; Nothing &lt;*&gt; Just &quot;woot&quot;
277277
Nothing
278278
</pre>
279-
<p>We see how doing <span class="fixed">pure (+3)</span> and <span class="fixed">Just (+3)</span> is the same in this case. Use <span class="fixed">pure</span> if you’re dealing with <span class="fixed">Maybe</span> values in an applicative context (i.e. using them with <span class="fixed">&lt;*&gt;</span>), otherwise stick to <span class="fixed">Just</span>. The first four input lines demonstrate how the function is extracted and then mapped, but in this case, they could have been achieved by just mapping unwrapped functions over functors. The last line is interesting, because we try to extract a function from a <span class="fixed">Nothing</span> and then map it over something, which of course results in a <span class="fixed">Nothing</span>.</p>
279+
<p>We see how doing <span class="fixed">pure (+3)</span> and <span class="fixed">Just (+3)</span> is the same in this case. Use <span class="fixed">pure</span> if you’re dealing with <span class="fixed">Maybe</span> values in an applicative context (i.e. using them with <span class="fixed">&lt;*&gt;</span>), otherwise stick to <span class="fixed">Just</span>. The first four input lines demonstrate how the function is extracted and then mapped, but in this case, they could have been achieved by just mapping unwrapped functions over functors. The last line is interesting, because we try to extract a function from a <span class="fixed">Nothing</span> and then map it over something, which of course results in a <span class="fixed">Nothing</span>.</p>
280280
<p>With normal functors, you can just map a function over a functor and then you can’t get the result out in any general way, even if the result is a partially applied function. Applicative functors, on the other hand, allow you to operate on several functors with a single function. Check out this piece of code:</p>
281281
<pre name="code" class="haskell:hs">
282282
ghci&gt; pure (+) &lt;*&gt; Just 3 &lt;*&gt; Just 5
@@ -967,7 +967,7 @@ <h3>On newtype laziness</h3>
967967
direct conversion from one type to another.
968968
</p>
969969

970-
<h3><span class="fixed">type</span> vs. <span class="fixed">newtype</span> vs. <span class="fixed">data</span></h3>
970+
<h3><span class="fixed">type</span> vs. <span class="fixed">newtype</span> vs. <span class="fixed">data</span></h3>
971971

972972
<p>
973973
At this point, you may be a bit confused about what exactly the difference
@@ -1077,7 +1077,7 @@ <h3><span class="fixed">type</span> vs. <span class="fixed">newtype</span> vs. <
10771077
</p>
10781078

10791079
<p>
1080-
When we make a type, we think about which behaviors it supports, i.e. what it can
1080+
When we make a type, we think about which behaviors it supports, i.e. what it can
10811081
act like and then based on that we decide which type classes to make it an
10821082
instance of. If it makes sense for values of our type to be equated, we make it
10831083
an instance of the <span class="fixed">Eq</span> type class. If we see that our
@@ -1255,7 +1255,7 @@ <h3><span class="fixed">type</span> vs. <span class="fixed">newtype</span> vs. <
12551255
<p>
12561256
The first two state that <span class="fixed">mempty</span> has to act as the
12571257
identity with respect to <span class="fixed">mappend</span> and the third says
1258-
that <span class="fixed">mappend</span> has to be associative i.e. that it the
1258+
that <span class="fixed">mappend</span> has to be associative i.e. that it the
12591259
order in which we use <span class="fixed">mappend</span> to reduce several
12601260
monoid values into one doesn’t matter. Haskell doesn’t enforce these laws, so we
12611261
as the programmer have to be careful that our instances do indeed obey them.

0 commit comments

Comments
 (0)