And so, to Haskell!

Wrapping up Clojure

I really enjoyed what i learned about Clojure last week. I notice an interesting thing: if i don’t do the exercises, i feel as if i don’t like the language. But when i actually try them out and solve a few problems for myself, i find i like it.

I like Clojure but i think that’s really because i like Lisp. For me, Clojure just seemed to add a bunch more keywords that i had to remember. Do i really need defprotocol and defrecord, just because they map to Java interfaces and types? I’d rather do without them. And the lack of support for automatic tail-optimised recursion disappointed me. Sure, you can do it explicitly … and that introduces another two Clojure keywords.

I want to get back to the day 3 exercises at some point, but Seven Languages in Seven Weeks is fast-paced and before i know it we’re into the last language!

And now, Haskell

I somehow feel that the whole book has been leading to this. We’ve seen functional elements in most of the languages, but now we get to a language with no excuses, no exceptions. It is uncompromisingly functional. And i love it.

I like strong typing, i like immutability, and i like the power of functions. Haskell is bringing them all together for me, as if it was my perfect dream language, created just for me! Well, i’m only just starting, so we’ll see if this perception continues :)

Just looking at the examples, and trying them out, i get an overall feeling of beauty in simplicity. Haskell is wonderful.

For example

Filtering a list to just the even numbers in the list. The book gives an example using recursion:

allEven :: [Integer] -> [Integer]
allEven [] = []
allEven (h:t) = if even h then h:allEven t else allEven t

The pattern match says that when you get to an empty list you return the empty list.

The tail-optimised recursion checks whether the head of the list is even, and if so includes it in the result, along with the even numbers of the rest of the list. Otherwise, it doesn’t.

We can also solve it with list comprehension. I first tried this:

allEven :: [Integer] -> [Integer]
allEven list = [if even x then x else 0 | x <- list]

I was putting the check into the expression and actually replacing odd numbers with zeros. Not a great solution. Then i remembered we can put a filter on the input side to ensure that only even numbers go in. Suddenly it becomes beautifully simple:

allEven :: [Integer] -> [Integer]
allEven list = [x | x <- list, even x]

Where Clojure felt cluttered with syntax, Haskell feels very minimal and concise.

Reversing a list

Well, this is too easy, so i expect they want me to do something more than just use the built in reverse keyword:

reverseList :: [Integer] -> [Integer]
reverseList list = reverse list

I think recursion is going to be the way to go with this. Split the head and tail and stick them back in the other order. Now then, what’s wrong with this?

reverseList :: [Integer] -> [Integer]
reverseList [] = []
reverseList (h:t) = reverseList(t):h

It gives a compile error:

Couldn't match expected type `Integer' with actual type `[Integer]'
In the return type of a call of `reverseList'
In the first argument of `(:)', namely `reverseList (t)'
In the expression: reverseList (t) : h

It must have something to do with type checking when constructing a list. I wondered whether it needed a few more guards:

reverseList :: [Integer] -> [Integer]
reverseList [] = []
reverseList [x] = [x]
reverseList [x,y] = [y,x]
reverseList (h:t) = reverseList(t):h

No. I think the problem is you can’t use this h:t style list construction with the way i’m imagining you can.

Whilst you can do this:


You cannot do this:


Basically, the head has to be an element, and the tail has to be a list.

However, we can use addition to join lists:

[2,3] ++ [1]

So the answer is:

reverseList :: [Integer] -> [Integer]
reverseList [] = []
reverseList (h:t) = reverseList(t) ++ [h]

Enough for now

This is taking a long time and it’s probably getting boring for my readers!

I will try to do a bit more on Haskell and publish it to my github: sermoa/7languages7weeks/week7-haskell


4 comments on “And so, to Haskell!

  1. For the evens function, what about this:

    evens = filter even

    List comprehensions combine a few things, but all you need in this case is filter, so using it on its own is cleaner. Also, you don’t need to use the list paramater – this is known as point fre style.

    You can’t do [2,3]:1 because : is what lisp calls cons. It constructs a cons cell with a data element and what I think of as a pointer to the rest of the linked list.

  2. I’ve never heard of this Clojure. I’d better check this out.

    Nice to be here. I came upon here from Aimee mychores. Lovely blog. Looking forward for more interesting posts. Cheers! :-)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s