Today I thought I would write a little about Haskell. This year I decided to learn this language and revisit the world of functional programming. After spending a month with it there are things that I understand much better, but I’d be lying if I said it was easy.
In order to learn Haskell, and functional programming in general, you really have to change the way you think about programming. One thing that has been especially hard on me has been the type system where, in a non-strict language, types really can take on a whole new meaning. Non-strict languages tend to have a little uncertainty about when expressions are evaluated so you end up defining functions which end up being totally different types than you expected take the problem of the IO() monad:
getAFile theFile = do
li <- readFile theFile
return (words li)
this function opens a file, breaks the file into a list of words and returns the list. You might ask yourself why I didn’t do this:
getAFile theFile = words (readFile theFile)
afterall, it seems like the evaluation of readFile would happen immediately and it would return a String no? Not quite… see, it actually has the type IO String. As mentioned above, IO is a monad and monads extend the normal type system as well as storing function results and side-effects. In light of this, however, the words function does not know how to evaluate. but by doing this:
li <- readFile theFile
li will have the type that we really expact because it will contain the result of the evaluation. You should also know that return doesn’t do what you expect either… it has the net effect of converting the list of words into type: IO [String] which I do here because the next function that I will call will take this particular type. return is a common and very useful thing to have when performing operations involving monads.
So as you can see… for an imperative programmer this can get pretty hairy. I get the feeling that this will come a little easier as I understand more about the language. I don’t want to give the impression that I don’t like Haskell, quite the contrary I think it is incredibly useful. I set about thinking to use it as a prototyping tool for algorithms but now I think it has a strong place in my repetoir. Here’s a good example:
Computing the sum of a Geometric Series at a given itteration: 
Here’s something in C, just to have to compare against:
double gseries(double c, double r, int max)
{
int n;
double res = 0.0;
for (n = 0; n < max; n++)
{ res += (c * pow(r,n)); }
return res;
}
and now in Haskell:
gseries c r n = sum ( [(c*r^x) | x <- [0..n] ] )
Now lets look at something you can’t do in C:
gseries_inf c r = [(c*r^x) | x <- [0..] ]
This is basically an infinite list. This is allowed because of Lazy Evaluation Haskell will only evaluate what it needs in order to give you the information:
*Main> (gseries_inf 1 1.9) !! 100
7.505162419825193e27
*Main> (gseries_inf 1 1.9) !! 1000
5.6702336219128545e278
*Main> (gseries_inf 5 1.9) !! 1000
2.8351168109564274e279
Haskell is well suited for a wide variety of tasks and has earned its own place in my toolbox.