The Evolution of the Imperative Programmer

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.

Leave a comment

4 Comments.

  1. gseries is a one line function but while I was learning the language and features here is what I had come up with:

    {- Haskell functions to calculate geometric series -}
    range s e = if s > e
    then []
    else s : range (s + 1) e

    lsum :: (Num lnum) => [lnum] -> lnum
    lsum (x:xs) = x + lsum xs
    lsum [] = 0

    {- Compute a geometric element -}
    gseries, gelem :: (Floating d, Integral n) => d -> d -> n -> d
    gelem c r o = c * r^o
    gseries c r n = lsum (gseries_elems c r n)

    {- Create a Geometric Series from the given inputs -}
    gseries_elems :: (Floating d, Integral n) => d -> d -> n -> [d]
    gseries_elems c r n = [ gelem c r x | x <- range 0 n ]

  2. Hello!

    Always good to hear about new Haskell users! If you haven’t already, make sure to come and visit our IRC channel: #haskell on irc.freenode.net — it’s very beginner-friendly and there are lots of clever people around at most hours of the day to help with questions of any sort you might have while hacking.

    cheers!
    – Cale

  3. Thanks for the note, I will be sure to check it out!

  4. Hey, Matt, Michael here (Steph’s bud…lots of Michaels out there, :)

    I know this is a super old post, but I found myself looking into Haskell (actually, based on your recommendation, in the form of this very post, originally), and I *really* dig it. Of course, I’m not a hundredth the programmer you are, but I thought I check out Functional Programming in general (y’know, see what all the hype is about ;) , and I think I like it as much as Lisp/Scheme, actually, even though it seems very different to me in several ways (some of which are, as yet, unquantifiable, at least, to me). Either way, though, thanks, (very) belatedly, for the recommendation :) .

    Hopefully one of these days I’ll get to a point where I can actually use all this stuff I call myself trying to learn.

Leave a Reply


[ Ctrl + Enter ]