Thursday, April 04, 2013

A Pattern Language for Haskell System Programming?

Continuing on my previous blog entry (Haskell for the Working Programmer), it occurs to me that there needs to be a set of idioms to define a Haskell for System Programming.  Or, perhaps more strongly: There needs to be a Pattern Language for developing System Programs using Haskell.

When I say System Programs, I am stretching the term a bit to mean an application that touches the real world a lot. That is, it isn't so much focused on doing a ton of data manipulation or business logic, but spends most of its time interacting with the system (hardware, OS, or network) at hand.  This is the land of embedded development, network tools and server management.  Haskell can play here, but I don't see a lot of literature about how to do this.

Haskell is a rich ecosystem for implementing cutting edge ideas. This is its academic heritage and it keeps the language healthy and forward looking. But for us working programmers, we can't always be interrupted from our tasks to explore new mind blowing techniques (e.g. "Okay, I grok Monads, so let's get some work done... whoa, wait... Arrows? I need to start using Arrows?").

So, you want to build Home Monitoring base station (something to collect sensor data, analyze it and perform some action or notification via the Internet).  Oh, and it needs a built in web server for configuration.

How do you do this using Haskell?

That isn't quite a fair question. A Haskell newbie would not be advised to adopt such a big project until they've mastered the language a bit. So, let's ask again, but a little more focused:

I'm an Erlang/Clojure/ML/Scheme programmer (so I understand FP); I've played around with Haskell and now I want to implement my Home Monitoring base system. Where do I start?

That's better.

So, what is needed here is way to guide a developer towards their goal with just a subset of Haskell. (I've recently written over  3000 lines of Haskell for a commercial system. It doesn't sound like a lot, but since it was mostly system programming stuff, I leveraged lots of Hackage libraries and FFIs.  In retrospect, I would say that I used a fairly small  subset of advanced Haskell features to get the job done.)

An aside:  I mentioned  the phrase Pattern Language as opposed to Design Patterns.  I don't want to bring up an old war in the Pattern Community (is there an active Pattern Community these days?), but I am talking about a group of related Patterns (or Idioms) that you can select to help you build a specific thing. Patterns in a Pattern Language are not adhoc. Each Pattern leads to one or more Patterns you may choose to help you build the thing. Check out the original source for further understanding and information. (I'm too lazy to find a great example of a software Pattern Language for system programming, but you can look at my own 1997 contribution to the community: A Pattern language for User Interface Design for the general idea of what I am talking about.)

Now, where were we? Subset of Haskell...

This subset of Haskell wouldn't be restrictive. By all means, if an advanced Haskell technique helps get the job done or makes the program more manageable, then use it.  But Haskell has an ocean of ideas and new users are apt to drown in lieu of getting their project completed.

You don't need to master all of Haskell, just master what you need.  Just by using Haskell (in particular the type system), you are already on your way to constructing correct system programs.  (But, please remember to handle exceptions -- the monadic wrapped real world is full of unexpected behavior).

So, what next?  I don't know. I am wondering if something like The School of Haskell would be a good place to start building such a pattern language (where examples could be not only listed but tried out).

1 comment:

  1. Anonymous4:23 PM

    I'd suggest looking into "Free Monads" for constructing DSLs for your domain.

    The IOSpec package does this very successfully. It uses "Data types a la carte" to build up free monads which carve up the IO monad into smaller submonads. In this way, you can be sure that your code isn't doing things it shouldn't. For example, an action with type "IOSpec Read" is guaranteed to be unable to write to the system, for example.