You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/syntax-in-functions.html
+13-2Lines changed: 13 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -177,9 +177,9 @@ <h1 style="margin-left:-3px">Syntax in Functions</h1>
177
177
| density <= 1000.0 = "Have fun swimming, but watch out for sharks!"
178
178
| otherwise = "If it's sink or swim, you're going to sink."
179
179
</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 <spanclass="fixed">True</span>, then the corresponding function body is used. If it evaluates to <spanclass="fixed">False</span>, checking drops through to the next guard and so on. If we call this function with <spanclass="fixed">24.3</span>, it will first check if that's smaller than or equal to <spanclass="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 <spanclass="fixed">24.3</span> is less than <spanclass="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 <spanclass="fixed">True</span>, then the corresponding function body is used. If it evaluates to <spanclass="fixed">False</span>, checking drops through to the next guard and so on. If we call this function with <spanclass="fixed">24.3</span>, it will first check if that's smaller than or equal to <spanclass="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 <spanclass="fixed">24.3</span> is less than <spanclass="fixed">1000.0</span>, the second string is returned.</p>
181
181
<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 <spanclass="fixed">otherwise</span>. <spanclass="fixed">otherwise</span> is defined simply as <spanclass="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 <spanclass="fixed">False</span> (and we haven't provided an <spanclass="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 <spanclass="fixed">otherwise</span>. <spanclass="fixed">otherwise</span> is defined simply as <spanclass="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 <spanclass="fixed">False</span> (and we haven't provided an <spanclass="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>
183
183
<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>
184
184
<prename="code" class="haskell:hs">
185
185
densityTell :: (RealFloat a) => a -> a -> String
@@ -221,6 +221,17 @@ <h1 style="margin-left:-3px">Syntax in Functions</h1>
221
221
GT
222
222
</pre>
223
223
<divclass="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
+
<prename="code" class="haskell:hs">
226
+
densityTell :: String -> String
227
+
densityTell input
228
+
| Just density <-readMaybeinput,density<1.2 = "Wow! You're going for a ride in the sky!"
229
+
|Justdensity<-readMaybeinput,density<= 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
+
<divclass="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 <spanclass="fixed">Haskell98</span>) but were added to the next (called <spanclass="fixed">Haskell2010</span>).</div>
224
235
<aname="where"></a><h2>Where!?</h2>
225
236
<p>In the previous section, we defined a density calculator function and responder like this:</p>
0 commit comments