Constructing New Haskell Programs

Posted on July 2, 2013

Greg Weng recently asked on the Google+ Haskell page a question that newcomers to the Haskell programming language may ask: What is an intuitive structure to construct a new Haskell program?

A Google employee, Gregory Collins, responded with a refreshingly clear and simple suggestion:

TL;DR ---

Start by modeling the problem in the data domain. Identify the datatypes the program will need. What algebraic properties do they have? For example, if I can identify that a piece of data forms a Monoid, that opens several new options for guiding the design of the implementation --- it means that you can aggregate a collection of these objects in parallel, for instance. The same thing goes for identifying Functor, Applicative, Alternative, etc structures.

Once you know roughly what the inputs and outputs will be, and have modeled those types, start thinking about the type of the implementation. Every program starts with main, and begins life in the IO monad. Optionally, depending on what your program looks like, you may want to lift your computation into some other monad. For example: ReaderT if your program has a global read-only state that should be available everywhere, StateT if you're using a side-effecting process to mutate or grow a piece of data, or create your own custom monad here.

But stick to plain old IO where possible. The rest of the implementation process is a game of pushing as much of the program as possible into pure functions (they are much easier to test), and breaking problems down into small pieces of structure using the "standard toolbox". It's amazing how many computations are expressible using some combination of map/fold/filter/unfold/concat/scanl etc....

I will often stub out parts of the program I know I will need later with undefined just so that I can get a skeleton version of the program to typecheck.

All credit goes to Gregory Collins, the author of the awesome new io-streams library for I/O using streams.