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
* Remove DOS line endings (only present in some files)
Command: dos2unix docs/*.html
* Remove trailing whitespace
Command: sed -i 's/[ \t]*$//' docs/*.html
Co-authored-by: Stanislav (Stanley) Modrak <44023416+smith558@users.noreply.github.com>
Copy file name to clipboardExpand all lines: docs/higher-order-functions.html
+12-12Lines changed: 12 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -178,11 +178,11 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
178
178
[1,3,6,2,2]
179
179
</pre>
180
180
<p>You've probably noticed that each of these could be achieved with a list comprehension. <spanclass="fixed">map (+3) [1,5,3,1,6]</span> is the same as writing <spanclass="fixed">[x+3 | x <- [1,5,3,1,6]]</span>. However, using <spanclass="fixed">map</span> is much more readable for cases where you only apply some function to the elements of a list, especially once you're dealing with maps of maps and then the whole thing with a lot of brackets can get a bit messy.</p>
181
-
<p><spanclass="label function">filter</span> is a function that takes a predicate (a predicate is a function that tells whether something is true or not, so in our case, a function that returns a boolean value) and a list and then returns the list of elements that satisfy the predicate. The type signature and implementation go like this:</p>
181
+
<p><spanclass="label function">filter</span> is a function that takes a predicate (a predicate is a function that tells whether something is true or not, so in our case, a function that returns a boolean value) and a list and then returns the list of elements that satisfy the predicate. The type signature and implementation go like this:</p>
182
182
<prename="code" class="haskell:hs">
183
183
filter :: (a -> Bool) -> [a] -> [a]
184
184
filter _ [] = []
185
-
filter p (x:xs)
185
+
filter p (x:xs)
186
186
| p x = x : filter p xs
187
187
| otherwise = filter p xs
188
188
</pre>
@@ -204,11 +204,11 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
204
204
<p>All of this could also be achived with list comprehensions by the use of predicates. There's no set rule for when to use <spanclass="fixed">map</span> and <spanclass="fixed">filter</span> versus using list comprehension, you just have to decide what's more readable depending on the code and the context. The <spanclass="fixed">filter</span> equivalent of applying several predicates in a list comprehension is either filtering something several times or joining the predicates with the logical <spanclass="fixed">&&</span> function. </p>
205
205
<p>Remember our quicksort function from the <ahref="recursion.html">previous chapter</a>? We used list comprehensions to filter out the list elements that are smaller than (or equal to) and larger than the pivot. We can achieve the same functionality in a more readable way by using <spanclass="fixed">filter</span>:</p>
206
206
<prename="code" class="haskell:ghci">
207
-
quicksort :: (Ord a) => [a] -> [a]
208
-
quicksort [] = []
209
-
quicksort (x:xs) =
207
+
quicksort :: (Ord a) => [a] -> [a]
208
+
quicksort [] = []
209
+
quicksort (x:xs) =
210
210
let smallerSorted = quicksort (filter (<=x) xs)
<p>Let's take an in-depth look into how this fold happens. <spanclass="fixed">\acc x -> acc + x</span> is the binary function. <spanclass="fixed">0</span> is the starting value and <spanclass="fixed">xs</span> is the list to be folded up. Now first, <spanclass="fixed">0</span> is used as the <spanclass="fixed">acc</span> parameter to the binary function and <spanclass="fixed">3</span> is used as the <spanclass="fixed">x</span> (or the current element) parameter. <spanclass="fixed">0 + 3</span> produces a <spanclass="fixed">3</span> and it becomes the new accumulator value, so to speak. Next up, <spanclass="fixed">3</span> is used as the accumulator value and <spanclass="fixed">5</span> as the current element and <spanclass="fixed">8</span> becomes the new accumulator value. Moving forward, <spanclass="fixed">8</span> is the accumulator value, <spanclass="fixed">2</span> is the current element, the new accumulator value is <spanclass="fixed">10</span>. Finally, that <spanclass="fixed">10</span> is used as the accumulator value and <spanclass="fixed">1</span> as the current element, producing an <spanclass="fixed">11</span>. Congratulations, you've done a fold! </p>
321
-
<p>This professional diagram on the left illustrates how a fold happens, step by step (day by day!). The greenish brown number is the accumulator value. You can see how the list is sort of consumed up from the left side by the accumulator. Om nom nom nom! If we take into account that functions are curried, we can write this implementation ever more succinctly, like so:</p>
321
+
<p>This professional diagram on the left illustrates how a fold happens, step by step (day by day!). The greenish brown number is the accumulator value. You can see how the list is sort of consumed up from the left side by the accumulator. Om nom nom nom! If we take into account that functions are curried, we can write this implementation ever more succinctly, like so:</p>
322
322
<prename="code" class="haskell:hs">
323
323
sum' :: (Num a) => [a] -> a
324
324
sum' = foldl (+) 0
@@ -340,7 +340,7 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
340
340
<p>Of course, we could have implemented this function with a left fold too. It would be <spanclass="fixed">map' f xs = foldl (\acc x -> acc ++ [f x]) [] xs</span>, but the thing is that the <spanclass="fixed">++</span> function is much more expensive than <spanclass="fixed">:</span>, so we usually use right folds when we're building up new lists from a list.</p>
341
341
<imgsrc="https://s3.amazonaws.com/lyah/washmachine.png" alt="fold this up!" class="right" width="250" height="205">
342
342
<p>If you reverse a list, you can do a right fold on it just like you would have done a left fold and vice versa. Sometimes you don't even have to do that. The <spanclass="fixed">sum</span> function can be implemented pretty much the same with a left and right fold. One big difference is that right folds work on infinite lists, whereas left ones don't! To put it plainly, if you take an infinite list at some point and you fold it up from the right, you'll eventually reach the beginning of the list. However, if you take an infinite list at a point and you try to fold it up from the left, you'll never reach an end! </p>
343
-
<p><em>Folds can be used to implement any function where you traverse a list once, element by element, and then return something based on that. Whenever you want to traverse a list to return something, chances are you want a fold.</em> That's why folds are, along with maps and filters, one of the most useful types of functions in functional programming.</p>
343
+
<p><em>Folds can be used to implement any function where you traverse a list once, element by element, and then return something based on that. Whenever you want to traverse a list to return something, chances are you want a fold.</em> That's why folds are, along with maps and filters, one of the most useful types of functions in functional programming.</p>
344
344
<p>The <spanclass="label function">foldl1</span> and <spanclass="label function">foldr1</span> functions work much like <spanclass="fixed">foldl</span> and <spanclass="fixed">foldr</span>, only you don't need to provide them with an explicit starting value. They assume the first (or last) element of the list to be the starting value and then start the fold with the element next to it. With that in mind, the <spanclass="fixed">sum</span> function can be implemented like so: <spanclass="fixed">sum = foldl1 (+)</span>. Because they depend on the lists they fold up having at least one element, they cause runtime errors if called with empty lists. <spanclass="fixed">foldl</span> and <spanclass="fixed">foldr</span>, on the other hand, work fine with empty lists. When making a fold, think about how it acts on an empty list. If the function doesn't make sense when given an empty list, you can probably use a <spanclass="fixed">foldl1</span> or <spanclass="fixed">foldr1</span> to implement it.</p>
345
345
<p>Just to show you how powerful folds are, we're going to implement a bunch of standard library functions by using folds:</p>
346
346
<prename="code" class="haskell:hs">
@@ -437,8 +437,8 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
437
437
<p>But what about functions that take several parameters? Well, if we want to use them in function composition, we usually have to partially apply them just so much that each function takes just one parameter. <spanclass="fixed"> sum (replicate 5 (max 6.7 8.9))</span> can be rewritten as <spanclass="fixed">(sum . replicate 5 . max 6.7) 8.9</span> or as <spanclass="fixed">sum . replicate 5 . max 6.7 $ 8.9</span>. What goes on in here is this: a function that takes what <spanclass="fixed">max 6.7</span> takes and applies <spanclass="fixed">replicate 5</span> to it is created. Then, a function that takes the result of that and does a sum of it is created. Finally, that function is called with <spanclass="fixed">8.9</span>. But normally, you just read that as: apply <spanclass="fixed">8.9</span> to <spanclass="fixed">max 6.7</span>, then apply <spanclass="fixed">replicate 5</span> to that and then apply <spanclass="fixed">sum</span> to that. If you want to rewrite an expression with a lot of parentheses by using function composition, you can start by putting the last parameter of the innermost function after a <spanclass="fixed">$</span> and then just composing all the other function calls, writing them without their last parameter and putting dots between them. If you have <spanclass="fixed">replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))</span>, you can write it as <spanclass="fixed">replicate 100 . product . map (*3) . zipWith max [1,2,3,4,5] $ [4,5,6,7,8]</span>. If the expression ends with three parentheses, chances are that if you translate it into function composition, it'll have three composition operators.</p>
438
438
<p>Another common use of function composition is defining functions in the so-called point free style (also called the point<i>less</i> style). Take for example this function that we wrote earlier:</p>
439
439
<prename="code" class="haskell:hs">
440
-
sum' :: (Num a) => [a] -> a
441
-
sum' xs = foldl (+) 0 xs
440
+
sum' :: (Num a) => [a] -> a
441
+
sum' xs = foldl (+) 0 xs
442
442
</pre>
443
443
<p>The <spanclass="fixed">xs</span> is exposed on both right sides. Because of currying, we can omit the <spanclass="fixed">xs</span> on both sides, because calling <spanclass="fixed">foldl (+) 0</span> creates a function that takes a list. Writing the function as <spanclass="fixed">sum' = foldl (+) 0</span> is called writing it in point free style. How would we write this in point free style?</p>
444
444
<prename="code" class="haskell:hs">
@@ -452,7 +452,7 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
452
452
<p>In the section about maps and filters, we solved a problem of finding the sum of all odd squares that are smaller than 10,000. Here's what the solution looks like when put into a function.</p>
453
453
<prename="code" class="haskell:hs">
454
454
oddSquareSum :: Integer
455
-
oddSquareSum = sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
455
+
oddSquareSum = sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
456
456
</pre>
457
457
<p>Being such a fan of function composition, I would have probably written that like this:</p>
458
458
<prename="code" class="haskell:hs">
@@ -462,7 +462,7 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
462
462
<p>However, if there was a chance of someone else reading that code, I would have written it like this:</p>
Copy file name to clipboardExpand all lines: docs/index.html
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@
14
14
15
15
<title>Learn You a Haskell for Great Good! (up-to-date)</title>
16
16
<metaname="description"
17
-
content='An up-to-date community maintained version of the renowned "Learn You a Haskell" (LYAH) guide for Haskell.
17
+
content='An up-to-date community maintained version of the renowned "Learn You a Haskell" (LYAH) guide for Haskell.
18
18
Packed with artwork, pop culture references, and most importantly, useful example code, this guide teaches functional fundamentals in a way you never thought possible.'>
19
19
<metaname="keywords" content="computer science learn me a haskell learnyouahaskell haskell learning programming coding functional Learn You a Haskell for Great Good LYAH open source guide manual Miran Lipovaca wiki course teach">
0 commit comments