Learn You a Haskell for Great Good! - Miran Lipovaca [4]
doubleUs x y = x * 2 + y * 2
Note
Functions in Haskell don’t have to be defined in any particular order, so it doesn’t matter which function comes first in the baby.hs file.
Now save the file, and enter :l baby in GHCi to load your new function. Testing this function yields predictable results:
ghci> doubleUs 4 9
26
ghci> doubleUs 2.3 34.2
73.0
ghci> doubleUs 28 88 + doubleMe 123
478
Functions that you define can also call each other. With that in mind, we could redefine doubleUs in the following way:
doubleUs x y = doubleMe x + doubleMe y
This is a very simple example of a common pattern you will see when using Haskell: Basic, obviously correct functions can be combined to form more complex functions. This is a great way to avoid code repetition. For example, what if one day mathematicians figure out that 2 and 3 are actually the same, and you have to change your program? You could just redefine doubleMe to be x + x + x, and since doubleUs calls doubleMe, it would now also automatically work correctly in this strange new world where 2 is equal to 3.
Now let’s write a function that multiplies a number by 2, but only if that number is less than or equal to 100 (because numbers bigger than 100 are big enough as it is!).
doubleSmallNumber x = if x > 100
then x
else x*2
This example introduces Haskell’s if statement. You’re probably already familiar with if statements from other languages, but what makes Haskell’s unique is that the else part is mandatory.
Programs in imperative languages are essentially a series of steps that the computer executes when the program is run. When there is an if statement that doesn’t have a corresponding else, and the condition isn’t met, then the steps that fall under the if statement don’t get executed. Thus, in imperative languages, an if statement can just do nothing.
On the other hand, a Haskell program is a collection of functions. Functions are used to transform data values into result values, and every function should return some value, which can in turn be used by another function. Since every function has to return something, this implies that every if has to have a corresponding else. Otherwise, you could write a function that has a return value when a certain condition is met but doesn’t have one when that condition isn’t met! Briefly: Haskell’s if is an expression that must return a value, and not a statement.
Let’s say we want a function that adds one to every number that would be produced by our previous doubleSmallNumber function. The body of this new function would look like this:
doubleSmallNumber' x = (if x > 100 then x else x*2) + 1
Note the placement of the parentheses. If we had omitted them, the function would only add one if x is less than or equal to 100. Also note the apostrophe (') at the end of the function’s name. The apostrophe doesn’t have any special meaning in Haskell’s syntax, which means it’s a valid character to use in a function name. We usually use ' to denote either a strict version of a function (i.e., one that isn’t lazy), or a slightly modified version of a function or variable with a similar name.
Since ' is a valid character for function names, we can write a function that looks like this:
conanO'Brien = "It's a-me, Conan O'Brien!"
There are two things to note here. The first is that we didn’t capitalize Conan in the name of the function. In Haskell, functions can’t begin with capital letters. (We’ll see why a bit later.) The second thing to note is that this function doesn’t take any parameters. When a function doesn’t take any parameters, we usually call it a definition or a name. Because we cannot change what names (or functions) mean once we have defined them, the function conanO'Brien and the string "It's a-me, Conan O'Brien!" can be used interchangeably.
An Intro to Lists
Lists in Haskell are homogeneous data structures, which means they store several elements of the same type. We can have a list of integers or a list of characters, for example, but we can’t have a list made up of both integers and characters.