Why I want to play with Haskell

Posted by user on 27 Apr 2009

Haskell, a sort of LISP. The language with parenthesis. Lots of parenthesis. LISP has got lots of parenthesis, not Haskell. Not to say that there aren't parenthesis in Haskell.

Why the interest?

At the heart of many security and reliability issues in software engineering, lies the difference between the intent (what you want to do) and the result (what you actually do).

What can also happen is that you didn't correctly understand what the problem is (difference between perception and reality). At some point there is no tool left to accuse and you have to assume that - maybe - you did something wrong.

Several paragraphs where I say that generic programming is teh r0xx0r

A language like C++ has been designed to enable the programmer to do whatever he pleases without restrictions. What is often perceived as a flaw is actually a major feature.

The language evolved a lot since its first specification. Generic programming and template meta-programming are clearly a good direction: they enable us to write safe, concise and efficient code. One of the reasons is that they borrow much of the functional approach to problem solving.

Let me explain further.

How would you write, in C++, a code that fills an array with reversed indexes values? Ie for a 5 items array obtain : { 4, 3, 2, 1, 0 }.

Classic approach:

1
2
3
4
5
6
7
int generate_reversed(size_t s)
{
    int
a = new int [s ] ;
    for ( int i = 0, j = s - 1 ; i < s ; ++i, --j )
        a [i ] = j ;
    return a ;
}

There is some lack of elegance in this code, don't you think? I'm not talking about the function that returns a raw pointer. Sure, you could use a smart pointer, but this post is not memory management discussion.

The main problem with this code is that there are just too many ways to get it wrong. Validate your for. Make sure i condition is ok. Make sure that you have correctly initialized j. And that you didn't write ++j when you meant --j. Etc.

Hopefully in 2009 we can write:

1
2
3
4
5
6
int generate_reversed(size_t s)
{
    int
a = new int [s ] ;
    generate (a, a + s, [ & ] { return --s ; } ) ;
    return a ;
}

It's much harder to get things wrong. You're not writing the for condition, you just decrement the value and don't need to bother about indexing. Your safety and concision dramatically improved. You may not realize it, but You just made one step toward functional oriented programming.

Where we talk less about C++ and more about Haskell

Back to Haskell. So what's the fuss about it?

Let's see some code with the classic sort example:

1
2
3
4
qsort [ ]     = [ ]
qsort (x:xs ) = qsort ( filter ( < x ) xs ) ++
    [x ] ++
    qsort ( filter ( > x ) xs )

How transparent. Quick sort is really about dividing a list in two, everything below the pivot goes to the left, everything above goes to the right. As you can see Haskell doesn't bother you about where you want to save your list, how you want to swap or memory management (you don't event need to instantiate temporary lists!).

Functional is all about how you manipulate your inputs (functions). You don't specify in which variable iterators go, or how you need to allocate memory (Stack? Heap? Decisions... Decisions...)

For the purpose of fair comparison, here is a trivial implementation of quick sort in C++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template < typename Iterator, typename Predicate >
void qsort (Iterator first, Iterator last, Predicate pred )
{
    if (first == last )
        return ;

    Iterator start = first;
        Iterator pivot = partition(++start,
        last,
        bind2nd(pred, *first));

    swap(pivot, first);

    qsort(first, pivot, pred);
    qsort(++pivot, last, pred);
}

More code. More specifications. More possibilities for errors. Haskell enables you to write a code that you code formally validate. It also is perfect for writing complex algorithms that you would more easily maintain (because you would only need to maintain what it does, not how it does it).

Here comes the drawback train, next stop is you

Performances. If you need a low memory footprint and top notch performances, Haskell is a bad choice. Because guess what, not telling how to do things means a program will decide for you. Unless you think you are less intelligent than a program, you probably realize by now that there is a reason we didn't ditched all programming languages in favor of Haskell (or an equivalent).

I can already hear people telling me that the compiler will improve and speed will cease to be an issue. Sure. But somehow, I doubt you can wait 10 years to have your program run at the desired speed.

In addition, it requires to be able to shift your mind in functional mode. Some people are very comfortable with this mode, some other aren't. It may require some time to get used to.

So, what could we use Haskell for?

With a certain degree of mastery in Haskell, it's possible to prototype complex algorithms and logic with little code.

For environments where reliability comes before performance, Haskell is also a good choice.

One thing that's actually been on my mind for a while is to write test bots in Haskell. Your test bot needs to be as correct as possible (otherwise your test is useless) and doesn't need to be ultra fast. When I say test bot I also think about vulnerability scanners, stresses, analysis tools...

All that sort of thing that would require tons (tons !) of C++ and are very natural to write in functional oriented language.

Topics: c++, haskell, Uncategorized