Haskell: Impressions!

Haskell Logo I have been, for years dedicated to imperative languages like Java, Python and C++. I haven’t heard of functional programming at all in the past. In my final year in university however, I had to choose modules, a candidate was a “Functional Programming” module taught using Haskell. In this article, I will share my impressions about Haskell from a new starter perspective.

Before going any further with this story, let me give you a complete code that calculates all the perfect numbers for a given number n. Just for the motivation, you know. A positive integer is perfect if it equals the sum of all of its factors, excluding the number itself.

factors n = [x | x <- [1..n], n `mod` x == 0, x /= n]
perfects n = [x | x <- [1..n], sum(factors x) == x]

Yep, those two functions (you see lines, but they are functions!) is a complete Haskell program that calculates all the perfect numbers for a given number n. Wonderful!

Choosing the module

I did a comprehensive (a good word to do a pun here with Haskell’s list comprehensions) research about the modules I were interested, including asking opinions from last year students. The main opinion among students was: “If you are concern about getting a high grade, then this module is hard to achieve!”; some expressed their opinion that was interesting nevertheless, none really suggested with confidence that they would choose the module again. The reason wasn’t specifically to the module of course but how different the language and the way of thinking was of what they have been used to (i.e imperative language and imperative thinking).

I was a bit influenced by the opinions but I was sure that this module was for me. I took another advice. In specific, the year I had to choose the modules, I was doing my placement, so a very good friend of mine and colleague, David, who knew about functional programming but nevertheless haven’t had the chance to do such module in his student years, said the following: “Choose it now!”, he was looking to the syllabus and his reaction was “Applicatives?! That is cool, you even going to cover Monads?! Mate, you should definitely choose this module”. Without a second thought, I did chose the module.

How was at the end?

  • How did I find it? Amazing, extraordinary and cool.
  • Do I regret choosing it? God no!
  • If I did it well? I did it very well, more than what I was expecting, and probably better than other modules which were considered “easier”!

I don’t know if is the language itself that is very nice and interesting, but also the way the module was taught was very exciting, challenging, motivating and high-quality. Just to put it in context, we had two large assignments (50% of the module) the one was an emulator of an 8-bit processor which included the definitions of the processor’s assembly language and we had to improve its memory representation into a tree-like structure; and the second one was a very interesting game called “Boggle” and we had to code the computer opponent to enable interaction between human and computer which included Depth-First-Search-like algorithm, dictionary lookup into a Trie structure etc; unlikely you will ever find all the words my computer programmed algorithm will find. The exam - a very cool lab exam with no internet by the way - was about the famous game Scrabble. Anyway, enough with module-specific information, lets focus on Haskell now!

Functional Programming and Haskell is probably one of the best languages I have seen for a while, purely functional with non-strict semantics and strong static typing.

There are some concepts like Types, Classes etc that sounds familiar but they are not. They are different in one way or another.

Pure Functions, IO System, Laziness and Pattern Matching

I was impressed with how the language promotes the “no side-effects” of your functions. That is, given the same input into a function will always return the same output. There are sometimes of course, were you need to communicate with external entities, that will do cause side-effects like reading from the user or a file, but Haskell has a very interesting I/O system that I haven’t seen before in a programming language, that eliminates possible side-effected code being mixed with pure functions.

It was challenging though that you didn’t have basic things like for and while loops (just recursions and list comprehensions were the only way you could “loop” into a data structure, at least that I am aware of). Not to mention that you can not change the state of a data structure, you can’t, for example, traverse a data structure and manipulate one of its values and return back this manipulated data-structure, you have to reconstruct the data structure in most cases with the alterations you want.

Another powerful idea behind Haskell, is it’s laziness. Although I knew about lazy evaluation in some of the imperative languages, in Haskell lazy is a huge thing!

Pattern matching. What I can say about this. Pattern matching it was a new concept, not hard to understand, but once you learn about it, is unlikely that you will write a non-trivial code that won’t have pattern matching.

Higher-order functions

Higher-order functions is truly an amazing and powerful concept that Haskell support of course.

A higher-order function is not only in Haskell but also in other non-purely functional programming languages like Python, JavaScript, Java and Swift just to name few.

In simple words, a functions is of a Higher-Order if it does one of the following:

  • Takes one or more functions as its arguments
  • Returns a function

Some very nice, built-in, functions offered by Haskell are: map and filter.

map given a function and a list of values, will apply the function to each element in the list.

Prelude> plusOne x = x + 1
Prelude> addOne xs = map (plusOne) xs
Prelude> xs = [1,2,3,4,5]
Prelude> addOne xs
[2,3,4,5,6]

We could wrote the above with map (+1) xs instead, but I wanted to make clear the use of an obvious function.

filter on the other hand given a function (predicate) and a list of values will return all the items that match the predicate.

Prelude> evensWithAddedOne xs = filter even $ map (+1) xs
Prelude> xs = [1,2,3,4,5]
Prelude> xs
[1,2,3,4,5]
Prelude> evensWithAddedOne xs
[2,4,6]

even is a built-in function that given a number will return true if is even or false if is odd.

You can of course, define your own high-order functions if you wish, and is where things gets interesting.

Haskell Logo

Did you know that Haskell’s current logo was selected during a logo competition in 2009? That means the language had some other logos in the past. The current logo is called “Thompson-Wheeler logo”.

But what is really nice about the logo, is that it has a cryptic message, that relates with some of the language features. In specific it highlights the Monad symbol (>>=) and λ expressions (know as anonymous functions).

Of course in Haskell λ is represented with \ instead (for obvious reasons), so a lambda expression looks something like this \x -> x * x. But \ is used to represent the λ.

So you see a very nice logo combining the monad symbol (>>=) with the anonymous function symbol (λ-expression)

Conclusion

There is no point going through all the new concepts I have learned, I can write many more concepts and cool things but there is no point really, if you are new and you are seeking opinions about whether you should learn the language, all these terms and concepts may confuse you, which is not the point of this article.

I enjoyed learning a functional programming and I think Haskell is a very powerful language that, in my opinion, every programmer should at least play with.

If you choose the right path to learn the language or any functional programming language, be prepared to rethink the problem you are solving. In most of the cases, you need to stop thinking imperatively and rethink the problem in a functional way, otherwise you will conclude into a black-hole.

It requires a significant effort though to get your head around and understand the concepts and the language if you aim a high grade. But by no means, Functional Programming or Haskell itself will stop you from achieving your ambitious goals.

© 2019 Rafael Papallas
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.