Skip to content

Commit 49e3d68

Browse files
kephasulysses4ever
andauthored
Add pattern guards (#59)
* Add pattern guards * Update docs/syntax-in-functions.html Co-authored-by: Artem Pelenitsyn <a.pelenitsyn@gmail.com> Signed-off-by: Pierre Thierry <pierre@nothos.net> --------- Signed-off-by: Pierre Thierry <pierre@nothos.net> Co-authored-by: Artem Pelenitsyn <a.pelenitsyn@gmail.com>
1 parent 131ff59 commit 49e3d68

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

docs/syntax-in-functions.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ <h1 style="margin-left:-3px">Syntax in Functions</h1>
177177
| density &lt;= 1000.0 = "Have fun swimming, but watch out for sharks!"
178178
| otherwise = "If it's sink or swim, you're going to sink."
179179
</pre>
180-
<p>Guards are indicated by pipes that follow a function's name and its parameters. Usually, they're indented a bit to the right and lined up. A guard is basically a boolean expression. If it evaluates to <span class="fixed">True</span>, then the corresponding function body is used. If it evaluates to <span class="fixed">False</span>, checking drops through to the next guard and so on. If we call this function with <span class="fixed">24.3</span>, it will first check if that's smaller than or equal to <span class="fixed">1.2</span>. Because it isn't, it falls through to the next guard. The check is carried out with the second guard and because <span class="fixed">24.3</span> is less than <span class="fixed">1000.0</span>, the second string is returned.</p>
180+
<p>Guards are indicated by pipes that follow a function's name and its parameters. Usually, they're indented a bit to the right and lined up. A guard can be one of two things. The first is basically a boolean expression. If it evaluates to <span class="fixed">True</span>, then the corresponding function body is used. If it evaluates to <span class="fixed">False</span>, checking drops through to the next guard and so on. If we call this function with <span class="fixed">24.3</span>, it will first check if that's smaller than or equal to <span class="fixed">1.2</span>. Because it isn't, it falls through to the next guard. The check is carried out with the second guard and because <span class="fixed">24.3</span> is less than <span class="fixed">1000.0</span>, the second string is returned.</p>
181181
<p>This is very reminiscent of a big if else tree in imperative languages, only this is far better and more readable. While big if else trees are usually frowned upon, sometimes a problem is defined in such a discrete way that you can't get around them. Guards are a very nice alternative for this.</p>
182-
<p>Many times, the last guard is <span class="fixed">otherwise</span>. <span class="fixed">otherwise</span> is defined simply as <span class="fixed">otherwise = True</span> and catches everything. This is very similar to patterns, only they check if the input satisfies a pattern but guards check for boolean conditions. If all the guards of a function evaluate to <span class="fixed">False</span> (and we haven't provided an <span class="fixed">otherwise</span> catch-all guard), evaluation falls through to the next <em>pattern</em>. That's how patterns and guards play nicely together. If no suitable guards or patterns are found, an error is thrown.</p>
182+
<p>Many times, the last guard is <span class="fixed">otherwise</span>. <span class="fixed">otherwise</span> is defined simply as <span class="fixed">otherwise = True</span> and catches everything. This is very similar to patterns, only they check if the input satisfies a pattern but boolean guards check for conditions. If all the guards of a function evaluate to <span class="fixed">False</span> (and we haven't provided an <span class="fixed">otherwise</span> catch-all guard), evaluation falls through to the next <em>pattern</em>. That's how patterns and guards play nicely together. If no suitable guards or patterns are found, an error is thrown.</p>
183183
<p>Of course we can use guards with functions that take as many parameters as we want. Instead of having the user calculate the density of the substance on their own before calling the function, let's modify this function so that it takes a mass (in grams) and volume (in liters).</p>
184184
<pre name="code" class="haskell:hs">
185185
densityTell :: (RealFloat a) =&gt; a -&gt; a -&gt; String
@@ -221,6 +221,17 @@ <h1 style="margin-left:-3px">Syntax in Functions</h1>
221221
GT
222222
</pre>
223223
<div class="hintbox"><em>Note:</em> Not only can we call functions as infix with backticks, we can also define them using backticks. Sometimes it's easier to read that way.</div>
224+
<p>But wait! It's not the only kind of guards. Sometimes, you want to check not that an argument satifies some pattern, but that the result of some function does (and pattern match on the result, of course). That's what pattern guards are for:</p>
225+
<pre name="code" class="haskell:hs">
226+
densityTell :: String -&gt; String
227+
densityTell input
228+
| Just density <- readMaybe input, density &lt; 1.2 = "Wow! You're going for a ride in the sky!"
229+
| Just density <- readMaybe input, density &lt;= 1000.0 = "Have fun swimming, but watch out for sharks!"
230+
| Nothing <- readMaybe input :: (RealFloat a => Maybe a) = "You know I need a density, right?"
231+
| otherwise = "If it's sink or swim, you're going to sink."
232+
</pre>
233+
<p>The full syntax of guards is a series of either boolean expressions or patterns guards, separated by commas.</p>
234+
<div class="hintbox"><em>Note:</em> Haskell has been designed to be a language that evolves and includes the results of research and experimentation. Pattern guards were not included in the first stable version of Haskell (called <span class="fixed">Haskell98</span>) but were added to the next (called <span class="fixed">Haskell2010</span>).</div>
224235
<a name="where"></a><h2>Where!?</h2>
225236
<p>In the previous section, we defined a density calculator function and responder like this:</p>
226237
<pre name="code" class="haskell:hs">

0 commit comments

Comments
 (0)