Thank you for joining us for the second part of our Haskell series, you will find the previous article here where I give a quick introduction to Haskell's types and functions.
As promised, what we are going to cover in this article are: lists and function declarations. Let's start with the lists as we will need them in the next part:
Lists are essentials in Haskell (and functional programming in general) and are the most commonly used data structure:
Prelude> a = [1, 2, 3, 4, 5] Prelude> head a 1 Prelude> last a 5 Prelude> length a 5
A few functions comes out of the box to help us with Lists:
head returns the first element and
last the last one (be careful, it is not
tail will give you the whole list minus the first element). Then
length returns the number of elements in the list. Easy peasy.
Lists are very versatile, you can simply concatenate them together like so:
Prelude> a = [1,2,3,4,5] Prelude> b = [6,7,8] Prelude> a ++ b [1,2,3,4,5,6,7,8]
You will note that in Haskell we differentiate
+ (add) and
In order to access a specific index you can use the following:
Prelude> a [1,2,3,4,5] Prelude> a !! 0 1 Prelude> a !! 1 2
And based on what we learned above about concatenation, you can add an element at the beginning or the end of a list like so:
Prelude> a ++  [1,2,3,4,5,6] Prelude>  ++ a [0,1,2,3,4,5]
Now, let's have a look at list comprehensions, if you are coming from Python you will know what's up. If you do not, think of it as an expression to iterate through a list and apply some operations to obtain a new list.
Let's do a comparison Haskell/Python where we are going to double every element in a list:
Looks pretty similar, the expression is wrapped in square brackets. In the Haskell version we use a pipe
| to split what we will do to each elements of the list (left) and what is the source of the list (right).
And now, we would like to apply a predicate (which is essentially a filter - it is a very common thing to do) so we do not take in account, let's say, the number 3:
You will note that in Haskell, we use
/= to check for inequality instead of the usual
!= in most languages. One more thing, in Haskell predicates are separated by
, meaning that you could put many of them instead of writing
or and so on. For instance:
Prelude> a = [1,2,3,4,5] Prelude> [x * 2 | x <- a, x /= 3, x /= 4, x /= 5] [2,4]
In our previous article, we had a quick introduction about functions, as a reminder we wrote the following:
powerOfTwo x = powerOfX x 2 powerOfThree x = powerOfX x 3 powerOfX x y = x ** y
Those are simple functions to calculate the power of a number.
In Haskell, you could only write function implementations in theory but it is a good practice to write definitions with it. After all, it is a statically typed language, it would be a huge loss not to mention the types of your functions.
Let's write one for
powerOfTwo in our file
powerOfTwo :: Float -> Float
Nice, but before jumping to conclusions, let's define
powerOfX :: Float -> Float -> Float
Right, so basically, we do not differentiate parameters and return value. Which we will explain later on. As of now, let's just remember that the return value is the last one on the right.
And of course we can check our functions by using the very helpful
:t like so:
*Main> :t powerOfTwo powerOfTwo :: Float -> Float *Main> :t powerOfX powerOfX :: Float -> Float -> Float
So, now that we know about lists and function declarations and implementations, let's mix all of that for quintessential learning value:
We are going to write a function which takes an array of
Float and calculates their power of x. Let's create a new file
-- This is our function from fn.hs which we just copy/pasted here powerOfX :: Float -> Float -> Float powerOfX x y = x ** y -- This is our new function which goes through a list powerOfXForList :: [Float] -> Float -> [Float] powerOfXForList list y = [powerOfX x y | x <- list]
powerOfXForList's definition here: we take as an input 2 parameters:
listwhich is of type
[Float](this is our list of floats which we want to take to the power of something)
ywhich is of type
Float(this is our power of something)
And we are going to return 1 thing
[Float] which is a new list identical to the first one, except every element will have been calculated to the power of something.
Then we load it in
:l <filename> as we saw in the first article:
*Main> :l power.hs [1 of 1] Compiling Main ( power.hs, interpreted ) Ok, one module loaded.
Our functions are loaded in the environment, we can play with it a bit:
*Main> a = [1,2,3,4,5] *Main> powerOfXForList a 2 [1.0,4.0,9.0,16.0,25.0] *Main> powerOfXForList a 3 [1.0,8.0,27.0,64.0,125.0]
Everything looks good, we're done for now, let's take a break before the next article.
Two Down, around eight more articles to go. I do hope that this post instilled some curiosity even maybe a pet project in Haskell. In the next article we will discuss infix vs prefix functions and discover more about types.
PS: Part 3 can be found here.
If you have a problem and no one else can help. Maybe you can hire the Kalvad-Team.