
On 9 March 2011 17:18, Simon Peyton-Jones
I can't say a lot about any one example, obviously, but what would be great would be - an idea of how Haskell helped (esp if you have a head to head comparison) - code snippets that illustrate how lovely it all is - brief performance indicators *Insight* is the key word. I don't just want to say "Company X used Haskell to do Y" because that doesn't convey any re-usable insights or ideas. What is the essence?
For what it's worth… (I imagine you're looking for more speed-intensive projects, but I like talking about Haskell, so here goes) my pet project IRCd called Hulk[1]. I whipped up a simple IRCd in an evening, and then the next day we (the dev team where I work[4]) were using it! Each client runs as a lightweight thread. The initial version used MVars all over the place, basically imperative, typical sloppy "getting it done quickly" code. I rewrote it a couple days later so that only the code that accepts connections and responds on the sockets is impure (100~ lines), and all the main code is totally pure (700~ lines), written in a monad stack of reader (connection information), writer (replies) and state (user details) (I abuse them[2]). I wrote about 500 lines of the pure stuff before even running it, and it just worked. There is one MVar in the project, that holds a pure value of all the state, this along with totally pure code, which has the obvious benefits; testability, a kind of "transactional" isolation. Some things (like checking against a SHA1 encrypted password file) require IO, so I have a MonadProvider class[3], with methods for *providing* values that will be impurely-acquired in the real server, but while testing I can provide my own values in a pure Reader or whatnot (HUnit and even QuickCheck spring to mind). One benefit, which didn't occur to me until asked about it, is that I didn't have to think much about choosing to have a separate thread per client because threads are so light-weight, my (Common Lisper) colleague was taken aback, being used to only "expensive" OS threads. The process been running for the past three weeks and we use it for all our dev discussion and for displaying things from feeds with rss2irc like commits, service events, support tickets, etc. Not bad for a few evenings of hacking! Insights: (1) It's nice and actually practical to make everything pure apart from the truly non-pure things, the monad of which can be parametrized. (2) Use of light-weight threads feels very natural, letting you think as if you're working in a single thread (with, e.g. blocking sockets), with no real cost. (3) Rapid prototyping in Haskell is actually very easy and effective. [1]: https://github.com/chrisdone/hulk [2]: class Monad m => MonadProvider m where providePreface :: m (Maybe String) provideMotd :: m (Maybe String) provideKey :: m String providePasswords :: m String [3]: I could stick all these in the StateT, but I think Reader and Writer are like nice, statically-enforced documentation. newtype IRC m a = IRC { runIRC :: ReaderT (UTCTime,Conn) (WriterT [Reply] (StateT Env m)) a } deriving (Monad ,Functor ,MonadWriter [Reply] ,MonadState Env ,MonadReader (UTCTime,Conn)) [4]: FWIW, the development section of CREATE-NET, a research centre in Italy. We are hiring Haskellers for application dev…