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
This domain and repository is in no way affiliated with Miran Lipovača (the original author) and is being extended and modified with his permision as per the licence the original work was released under ([Creative Commons Attribution-Noncommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/)) as well as his literal statement encouraging modifiations to be made ([FAQ](http://learnyouahaskell.com/faq)).
38
+
This domain and repository is in no way affiliated with Miran Lipovača (the original author) and is being extended and modified with his permision as per the licence the original work was released under ([Creative Commons Attribution-Noncommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/)) as well as his literal statement encouraging modifications to be made ([FAQ](http://learnyouahaskell.com/faq)).
39
39
40
40
##
41
41
This work is licensed under a [Creative Commons Attribution-Noncommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/).
Copy file name to clipboardExpand all lines: docs/functionally-solving-problems.html
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,7 @@
32
32
</ul>
33
33
</div>
34
34
<h1>Functionally Solving Problems</h1>
35
-
<p>In this chapter, we'll take a look at a few interesting problems and how to think functionally to solve them as elegantly as possible. We probably won't be introducing any new concepts, we'll just be flexing our newly acquired Haskell muscles and practicing our coding skills. Each section will present a different problem. First we'll describe the problem, then we'll try and find out what the best (or least worst) way of solving it is.</p>
35
+
<p>In this chapter, we'll take a look at a few interesting problems and how to think functionally to solve them as elegantly as possible. We probably won't be introducing any new concepts, we'll just be flexing our newly acquired Haskell muscles and practicing our coding skills. Each section will present a different problem. First we'll describe the problem, then we'll try and find out what the best (or least bad) way of solving it is.</p>
<p>Usually when we write mathematical expressions in school, we write them in an infix manner. For instance, we write <spanclass="fixed">10 - (4 + 3) * 2</span>. <spanclass="fixed">+</span>, <spanclass="fixed">*</span> and <spanclass="fixed">-</span> are infix operators, just like the infix functions we met in Haskell (<spanclass="fixed">+</span>, <spanclass="fixed">`elem`</span>, etc.). This makes it handy because we, as humans, can parse it easily in our minds by looking at such an expression. The downside to it is that we have to use parentheses to denote precedence.</p>
38
38
<p><ahref="https://en.wikipedia.org/wiki/Reverse_Polish_notation">Reverse Polish notation</a> is another way of writing down mathematical expressions. Initially it looks a bit weird, but it's actually pretty easy to understand and use because there's no need for parentheses and it's very easy to punch into a calculator. While most modern calculators use infix notation, some people still swear by RPN calculators. This is what the previous infix expression looks like in RPN: <spanclass="fixed">10 4 3 + 2 * -</span>. How do we calculate what the result of that is? Well, think of a stack. You go over the expression from left to right. Every time a number is encountered, push it on to the stack. When we encounter an operator, take the two numbers that are on top of the stack (we also say that we <i>pop</i> them), use the operator and those two and then push the resulting number back onto the stack. When you reach the end of the expression, you should be left with a single number if the expression was well-formed and that number represents the result.</p>
<p>Cool, it works! One nice thing about this function is that it can be easily modified to support various other operators. They don't even have to be binary operators. For instance, we can make an operator <spanclass="fixed">"log"</span> that just pops one number off the stack and pushes back its logarithm. We can also make a ternary operators that pop three numbers off the stack and push back a result or operators like <spanclass="fixed">"sum"</span> which pop off all the numbers and push back their sum. </p>
95
+
<p>Cool, it works! One nice thing about this function is that it can be easily modified to support various other operators. They don't even have to be binary operators. For instance, we can make an operator <spanclass="fixed">"log"</span> that just pops one number off the stack and pushes back its logarithm. We can also make ternary operators that pop three numbers off the stack and push back a result or operators like <spanclass="fixed">"sum"</span> which pop off all the numbers and push back their sum. </p>
96
96
<p>Let's modify our function to take a few more operators. For simplicity's sake, we'll change its type declaration so that it returns a number of type <spanclass="fixed">Float</span>.</p>
<p>I think that making a function that can calculate arbitrary floating point RPN expressions and has the option to be easily extended in 10 lines is pretty awesome.</p>
128
-
<p>One thing to note about this function is that it's not really faulttolerant. When given input that doesn't make sense, it will just crash everything. We'll make a faulttolerant version of this with a type declaration of <spanclass="fixed">solveRPN :: String -> Maybe Float</span> once we get to know monads (they're not scary, trust me!). We could make one right now, but it would be a bit tedious because it would involve a lot of checking for <spanclass="fixed">Nothing</span> on every step. If you're feeling up to the challenge though, you can go ahead and try it! Hint: you can use <spanclass="fixed">reads</span> to see if a read was successful or not. </p>
128
+
<p>One thing to note about this function is that it's not really fault-tolerant. When given input that doesn't make sense, it will just crash everything. We'll make a fault-tolerant version of this with a type declaration of <spanclass="fixed">solveRPN :: String -> Maybe Float</span> once we get to know monads (they're not scary, trust me!). We could make one right now, but it would be a bit tedious because it would involve a lot of checking for <spanclass="fixed">Nothing</span> on every step. If you're feeling up to the challenge though, you can go ahead and try it! Hint: you can use <spanclass="fixed">reads</span> to see if a read was successful or not. </p>
129
129
<aname="heathrow-to-london"></a><h2>Heathrow to London</h2>
130
130
<p>Our next problem is this: your plane has just landed in England and you rent a car. You have a meeting really soon and you have to get from Heathrow Airport to London as fast as you can (but safely!).</p>
131
131
<p>There are two main roads going from Heathrow to London and there's a number of regional roads crossing them. It takes you a fixed amount of time to travel from one crossroads to another. It's up to you to find the optimal path to take so that you get to London as fast as you can! You start on the left side and can either cross to the other main road or go forward.</p>
0 commit comments