Haskell as an alternative to Perl for scripting tasks.

For the past couple of weeks I have been working with a very interesting system administrator. He’s responsible for maintaining a large number of Web servers, mail servers, and database servers. Like most system administrators, he employs a number of scripts he’s developed to automate a variety of tasks. While most sysadmins would use a language like Perl or Python for developing their scripts, this fellow uses Haskell. Of course, I asked him why he used Haskell. His answers really aren’t surprising to somebody who has used Haskell before.

The first benefit he found was that Haskell’s rich feature set allowed him a great deal of flexibility when it came to quickly getting scripts written. He was particularly fond of its excellent list handling capabilities, notably list comprehensions. Haskell’s pattern matching support was another plus for him.

He also found Haskell’s static typing to be essential. At one point, he told me something along the lines of, “When my program compiles and typechecks, it almost always works.” Not having to worry about unexpected type-related errors causing problems at runtime made him feel more comfortable with using Haskell for long-running scripts.

He also said he was impressed by GHC, the Haskell implementation he chose to use. Its interpreter allowed him to rapidly test out code snippets, but he could then eventually compile his code to machine code for greater performance.

Maybe it’s time for more system administrators to start looking into the use of Haskell for their scripting tasks. Although it’s no doubt not ideal for all users, it does offer many benefits that many users would find useful. Haskell seems to have made the life of this one administrator quite a bit easier, and might do the same for others.

24 Responses to “Haskell as an alternative to Perl for scripting tasks.”

  1. Jeff Forcier Says:

    Seems interesting that one of his benefits, list comprehensions, also exists in Python (unless Haskell’s are significantly different) and another one, integrated pattern matching, is of course what Perl is well known for.

    I certainly can’t argue with the static typing, as that’s always been a matter of preference or opinion. The interpreter-but-can-compile thing is again partially matched by Python, which has an interpreter, and compiles to bytecode, but doesn’t have a true compiler for machine code.

  2. Derek Elkins Says:

    Python got its list comprehensions from Haskell and “pattern matching” in Haskell doesn’t refer to integrated regular expressions, but to something else altogether. Haskell doesn’t have integrated regular expressions (though it has a library that makes them pretty convenient to use.)

    GHCi is a bytecode interpreter, the compiler, GHC, is a real compiler. GHCi can also load compiled code allowing you to get the best of both worlds albeit not as conveniently as many Lisp REPLs.

  3. Shawn Says:

    Jeff Forcier:

    Pattern matching is a different beast in Haskell than it is in Perl. In Haskell, pattern matching is how you bind arguments to a function to variables, in a very expressive and beautiful way. In Perl, pattern matching is regular expression matching. Both are good, but they’re not the same here.

  4. Rudolf Olah Says:

    Excellent stuff. Post some of the scripts if you can :D
    I wrote about using Scheme as a replacement for Perl/Ruby/Python for scripting tasks as well: http://neverfriday.com/blog/?p=31

  5. Zac Says:

    To Jeff:

    By pattern matching I’m pretty sure they don’t mean regex string patterns, but pattern matching in the way of functional languages parsing different calls. For example:

    factorial 0 = 1
    factorial n = n * f(n - 1)

    In the above (very trivial) example, if it matches n to be 0 then it returns 1, else it’ll multiply n by f(n - 1). I think the pattern matching you mention as perl was created for is more along the regex pattern matching.

    As far as python list comprehensions go, they’re not near as powerful ask their functional counterparts (haskell, ocaml, erlang and friends). At least not in my opinion, but I could be wrong as I haven’t played with python’s pattern matching much.

    Cheers,

    Zac

  6. Daniel Wagner Says:

    Hi Jeff!

    Yes, there are a lot of similarities between the various high-level languages, and I think they’re constantly borrowing good ideas from each other. This is a Good Thing; everyone benefits. The only thing I might point out about your comment is that “pattern matching” means something completely different in Haskell and in Perl.

    In Perl, as I understand it, pattern matching means matching strings to reg-exes. I’ve heard that having that is very useful, and Haskell does not have it (though it does have other powerful idioms, at least one of which gives you full LALR(k) language matching). What Haskell does have is a convenient way to differentiate between different constructors of a given type. It doesn’t sound like much, but it is a godsend for complicated logic flows and crops up in places you would least expect it.

    Fun fun! Happy coding,
    ~d

  7. Michael Campbell Says:

    Just once I’d like to see a functional programming post come up without the obligatory “but python does that too” comment. Yeah, we get it already.

    Today is evidently not the day for it.

  8. Anon Says:

    Jeff Forcier: “[…] integrated pattern matching, is of course what Perl is well known for.”

    Pattern matching in the context mentioned here has nothing to do with regular expressions which you had probably in mind when writing this. Cf. http://en.wikibooks.org/wiki/Haskell/Pattern_matching

  9. Dan S. Says:

    Jeff Forcier:

    In this case, regular expressions are not the pattern matching that was meant.

    If you scroll down to “pattern matching” in [ http://www.ocaml-tutorial.org/data_types_and_matching ], you’ll see a pretty trivial idea of what’s going on. (The language here is OCaml — very similar to haskell — only because I happened to have a bookmark to the tutorial there… )

  10. Daniel Says:

    Jeff: Python’s list comprehensions were inspired by Haskell’s, and pattern matching in this context does not mean what you think it does.

  11. Kevin Scaldeferri Says:

    @Jeff,

    Haskell pattern matching is a completely different thing from perl regular expression matching.

  12. James Says:

    ‘He also found Haskell? static typing to be essential. At one point, he told me something along the lines of, ?hen my program compiles and typechecks, it almost always works.?

    And when my Ruby code passes all its unit tests and/or specs, it, too, “almost always works”. More “always” than “almost”.

    Trolling aside, what’s made languages such a Haskell. that is, languages not clearly intended for scripting tasks (i.e., no shebang line) awkward for sysadmins is the lack of clear instructions and examples for writing and running basic scripts.

    Are there such resources for Haskell? Is it as easy to write the one-liner, edit-save-and-run “Hello world” script in Haskell as it is in Perl or Ruby?

    Do such scripts have to be *compiled* to run? Do they have easy access to environment variables, and snake-simple file handling and command line IO?

  13. Markus Says:

    I wonder how many more people are going to point out that pattern matching as implemented by Perl(i.e. regular expressions) is different than pattern matching in Haskell.
    That was pointed out something like the third post and I’m still reading about this rather obvious difference.

  14. Don Stewart Says:

    @james

    There’s a big difference between unit testing and type system checks. For one, you can forget a test, and no one will tell your till your program does the wrong thing.

    Haskell happily supports shebang lines. Here’s a hello world program:

    #!/usr/bin/runhaskell

    main = print “hello, world”

    statically typed and all. The benefit is that you can also compile this to native code if you like, something people only wish could be done in ruby (and as we see, this can mean serious performance and memory usage improvments):

    http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=ghc&lang2=ruby

  15. Jeff Forcier Says:

    Yikes, talk about a pile-on. I get the distinct impression that pattern matching != regex :)
    My apologies, I probably shouldn’t have posted without knowing more about the specifics of Haskell. I do want to state that I wasn’t meaning my comment to come across as a “that’s stupid, Python does it too” but more as a query - as someone *not* from the Haskell world, the reasons presented for using it as a scripting language didn’t sound like anything special, which is why I was confused. I should have made that more clear.

    Thanks for the clarifications - terminology’s a bitch sometimes :)

  16. Logan Says:

    @steve

    #!/usr/bin/runhaskell
    main = putStrLn “Hello, world!”

    No they don’t have to be compiled to run. I’m not sure if snake-simple means “as simple as python” or just “simple” but yes you have access to the env vars and yes using files isn’t any more complicated than ruby for example.

  17. Paul Prescod Says:

    Here are some links that seem relevant:

    blog.kfish.org/2006/12/introductory-haskell-programming-in.html

    http://www.cse.unsw.edu.au/~dons/data/Basics.html

    haskell.org/haskellwiki/Simple_unix_tools

  18. James Says:

    Don, Logan: Thanks very much for the examples. That’s a big help trying this out for myself.

    Paul: Thanks for the links.

    BTW, I’ve been trying to learn Haskell for the last few months, and many of the tutorials, and both books I’ve read (SOE, and Hutton’s Programming in Haskell) take a pretty academic and hand-wavy approach to the language. That is, there is much talk of syntax and abstract concepts, and very little “Here’s how you actually edit and run a complete program that does something instantly useful.” (Those two books are especially poor in that they present “code” using typographic symbols you will never actually type into an editor.)

    Thanks again for the interesting topic and pointers.

  19. Mark Says:

    I have to say, this blog post was very thin on content. It would be nice if someone who knows would explain what Haskell pattern matching is, and it would also have helped the original post if he could have convinced the guy to part with some actual source code so we could have a look. I’m left wondering why the points mentioned in support of Haskell are even relevant to anything. Admittedly this is due to my ignorance, which, to my point, is just as profound now as it was before I read the post.

  20. Daniel Wagner Says:

    @James: You might get a little surprise if you tried typing in the code just as you saw it, symbols and all. ;-)
    Haskell allows you to define new infix operators, as long as they’re composed only of symbols. So, for example, the Prelude includes the definition

    f . g x = f (g x)

    which defines the (.) operator to compose functions. Just keep in mind that the style in papers on Haskell is to “smoosh together” all the characters in an operator. So, the (++) operator just becomes a horizontal lines with two vertical bars very close together. If you mentally space out the symbols in the papers, though, you’ll probably get valid Haskell. =)

    g’luck,
    ~d

  21. Anon Says:

    Sucks to be his employers. I can just see it now, for whatever reason: “Experienced sys admin sought; Haskell a requirement”. Yep that ought to get plenty of applicants.

  22. Anon Says:

    Oh yeah, and anyone who says Haskell has a rich feature set in comparison to Perl is an idiot. The feature set mountain of Perl is CPAN which is instantly and easily installable modules for just about everything.

  23. Bulat Says:

    there is a great page http://haskell.org/haskellwiki/Simple_unix_tools which shows how to implement some simple filters in Haskell

    in the past, my languages of choice was perl, then ruby. they are especially great on shell scripting side, we all know. a few years ago when i tried to implement the same script (which benchamarked compression software) in ruby and haskell, i’ve found that amount of code implementing main task was essentially the same, but in Haskell version, i’ve need to add the same amount of code to implement simple things omitted in standard libs - such as getFileSize or trimSpaces

    with good libraries, i think, Haskell is a good alternative to classic scrpting langueges. it excels when you need to do complex data processing, but it’s bad part is that each action should be written as separate statement, i.e. you can’t write

    if getFileSize f1 < getFileSize f2

    but you should write

    s1 <- getFileSize f1; s2 <- getFileSize f2; if s1<s2

    it also doesn’t have convenient control structures. OTOH, you can define your own ones. one of my beloved examples was an ‘onException’ control structure which also catched ^Breaks :)
    you should also know that Linspire project now selected Haskell as its main scripting language (you can read about this in “A History of Haskell: being lazy with class” http://research.microsoft.com/~simonpj/papers/history-of-haskell/history.pdf )

    overall, i think that Haskell will be interesting for admins with “mathematical”, abstractions-oriented mind

    one more interesting thing in Haskell is that it supports multi-core multi-threading execution with overlapped I/O with a great (erlang-like) model of passing data between threads. probably, erlang will be an interesting scripting laguage too ;)

  24. Lemming Says:

    Bulat, what about

    b <- liftM2 (<) (getFileSize f1) (getFileSize f2)
    if b then x else y

    Ok, still more cumbersome than imperative programming, but less worse. :-)
    I remember, you proposed ‘bool’. Then it becomes:

    liftM2 (>= bool x y

Leave a Reply

*
To protect against spam, please type the word in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word