Hari's Corner

Humour, comics, tech, law, software, reviews, essays, articles and HOWTOs intermingled with random philosophy now and then

Five tips about Functional Programming for a Haskell newbie from a Haskell newbie

Filed under: Tutorials and HOWTOs by Hari
Posted on Mon, Nov 7, 2011 at 15:43 IST (last updated: Mon, Nov 7, 2011 @ 16:15 IST)

In this series < Previous Next >
Following up from my previous article, I have made some progress and gained some insights about Haskell. Here I will share some of my "insights" of how to approach the forbidding task of learning a functional programming language from the eyes of a newbie. I realize of course, these might not be correct from a purely conceptual point of view, but it's more of a mental approximation of how I see them at the moment. I think some of these tips might be useful for other newbies to Haskell as well.

Think of functions as transformers, not as containers of actions

Adjusting to the functional programming paradigm is always a challenge, and I think one key adjustment is how you identify "functions." In procedural or OOP, functions (or rather methods) are containers or groups of actions performed sequentially. In functional programming language functions should be seen as transformers, in the mathematical sense: it takes an input and transforms it to something else.

This makes it a lot easier to learn functional composition, higher order functions and so on. This change is actually not as easy as it sounds, though. For an experienced traditional programmer, functions, procedures or methods all mean very similar things and getting old ideas out of the head can be a bit tough. So don't worry too much if it doesn't sink in at once.

Recursion is easy: if you work it out backwards

One thing about recursion is how intuitive and smart a solution looks when it is presented. But not all newbies to the FP paradigm can "get" how it can replace the normal for and while loops in procedural languages.

My advice: when approaching a problem that demands recursion, don't start from the recursive case. Rather think about the base case first and how you get there from the more general cases. This is actually something I find rather intuitive, but it is not the obvious way of thinking about a solution to a problem coming from an imperative programming background.

Try to write your own working code and go from there

Tutorials are nice, but they are just learning aids. I would suggest avoiding the temptation to look up solutions from tutorials when you get a bit more experienced.

Actually writing working code, even for reasonably trivial problems, can be enormously fun and satisfying, particularly in Haskell. Writing code that compiles properly can be a thrill, because Haskell's strong typing system really works well to identify MOST kinds of obvious mistakes, but of course, writing a correct program is more than syntax correctness. For simple programs, if it compiles, it's correct. :)

My order of practicing writing your own programs would be something like this (of course, feel free to disagree with this list):
  1. Simple calculator that takes two values and performs an action based on user input. Areas of a triangle, area of parallelogram etc.
  2. Fibonacci series, and other basic recursive patterns.
  3. A Caesar-cipher encryption function.
  4. A program that reads a string of characters and identifies it as either an integer, a floating point number or a word.
  5. A program that reads an integer number and outputs its English equivalent. E.g. 1200 : one thousand two hundred. (this could be where it gets harder though)
  6. A postfix (or reverse polish) expression evaluator.

Once you write the code, find out from experienced Haskell programmers what mistakes you made and how you can write it better. The Haskell community is full of generous and kind folk who help newbies a lot (#haskell at FreeNode is particularly nice).

After that, you can pick and choose, but generally try to advance one concept at a time. :)

Thinking before a single line of code is the right approach

In Haskell circles, it is a common saying that you would spend more time thinking about the problem than implementing it. This is not strictly true, particularly for a newbie, but it has merit which you will appreciate as you progress. In the functional programming paradigm, solutions are worked out in a methodical and mathematical fashion and thinking ahead is often a big part of it.

Finally don't pressurize yourself to learn quickly

One mistake is trying to swallow too many concepts at once. It doesn't work like that. Everything takes time to sink in, because it's all so new and different. Learning yet another procedural/OOP programming language is easy if you already have some background in procedural/OOP programming, because the concepts are familiar. Not so with FP.

Haskell seems to have a reputation for being hard and academically oriented, even in Functional Programming circles. And actually reinforcing that idea can lead to mental blocks in a newbie. Learning it with an open mind can work wonders. Allow the learning to happen at its own pace and enjoy the process. Thinking of "how I will ever be productive in Haskell" is counter-productive. Rather learn for the sake of learning and feel good about the knowledge you already possess.

Hope this helps. As always I welcome feedback and tips from the Haskell community.

In this series

2 comment(s)

  1. One should be careful when thinking of functions as transformers because the values passed to functions are immutable. The values you give to functions are not changed themselves but are used to create new values. This is an important property of purely functional programming language that can seem pretty alien if you're used to von Neumann-style mutable memory languages.

    Secondly, in relation to what you say about learning slowly, I would like to reiterate the comment on your last post: I think Scheme is a better starting point for learning functional programming. Haskell is two things: it is purely functional, but it is also strongly typed and you have to learn both of them at the same time and that can be daunting. Undoubtedly the combination of pure functions and algebraic data types is very powerful, but it can also be difficult to understand in its entirety.

    Comment by Shrutarshi Basu (visitor) on Tue, Nov 8, 2011 @ 00:15 IST #
  2. Shrutarshi Basu, thanks. Yes, I should have added that caveat. Immutability is an important concept to grasp.

    Comment by Hari (blog owner) on Tue, Nov 8, 2011 @ 07:29 IST #

Comments closed

The blog owner has closed further commenting on this entry.