This semester, I was assigned a task that was meant to practice the knowledge gathered about the functional programming paradigm during a CS course. The task was to develop an abstract data type for a processes network and a way to automatically convert it to Miranda executable code.

A processes network is an idea based on the data flow paradigm: a network is a set of processes that cooperate together to reach a result. A process is an entity that produces a single output based on a set of inputs, which can be other processes or parameters fed in by the user (think of a shell pipeline). The process itself is modeled by a function, either defined in another network or provided by the language natively. A program is then composed of a set of these networks. Functional languages are ideal to implement a program modeled using this paradigm.

Our program could be written either in Miranda (the language taught in class) or Haskell. My partner and I decided to go for the latter because it is a live language (Miranda seems dead), it is free and there is much more information for it than for the former. The drawback was that we were on our own learning it and it was really tough to get started, but it has been a very rewarding experience.

But why is functional programming so interesting? It is a paradigm where the sole basis of execution is the evaluation of expressions. These expressions are composed of functions (either native ones or defined by the user), so the programmer's task is to write new functions and compose them to achieve the correct data transformation. There is no notion of memory nor variables as in imperative languages. And in Haskell's case, everything just feels correct; if something is not well understood or does not fit the paradigm, it is not included in the language.

Here are some of the key items to functional programming; some of them may be Haskell-specific:
  • Functions have no side effects: there are no global variables.
  • There are no loops: algorithms have to be thought in recursive terms. Although this may seem difficult at first, it is not so much thanks to the built-in functions.
  • Everything has a mathematical background, which makes formal proofing easier than with imperative languages. For example, one can define an abstract data type based exclusively on its formal construction equations: in the stack's case, it'd be defined by means of an empty constructor and a "push" one.
  • High-order functions: ever thought to pass a function as a parameter to another one? C++ has some kind of support for this through predicates, but in a functional language this idea is the key to success: it is used extensively and is much more powerful.
  • Lazy evaluation: a neat idea. It makes the treatment of infinite or undefined objects possible. This concept is not generic to the paradigm but is commonly associated with it.
  • Strong typed: Haskell is very strong typed but it does not require you to manually specify types (although you can); isn't it strange? The compiler/interpreter comes with a powerful type deduction system that does the work for you and ensures everything makes sense, type-wise speaking.
So far I like the language and the paradigm very much, and I have only grasped their surface. There are tons of things I still do not know how to do, not to mention that it is quite hard to avoid imperative programming thinking. I'm thinking to use Haskell to write at least one of my personal projects to really experience its power.

If you have some spare time and are willing to learn something new, give functional programming languages — hmm, Haskell — a try. Just get the Hugs interpreter, the Haskell tutorial and get started! I bet you'll like it ;-)

Comments from the original Blogger-hosted post: