The Clean language uses uniqueness types to handle I/O in a purely functional setting. Why did the Haskell committee go with monads instead? Were there other proposals for handling state that the committee investigated but decided against?

Note: I'm not looking for a holy war between monads and other forms of computing. Let's keep the topic to just the committee's choices regarding I/O.


2 Answers 2


According to A History of Haskell: Being Lazy With Class (see section 7) three different models were considered initially: streams, continuations and "world passing" (I don't know much about Clean, but it sounds like this is the Clean way?).

The last paragraph of section 7.2 indicates that the uniqueness type concept wasn't developed at this time:

This “world-passing” model was never a serious contender for Haskell, however, because we saw no easy way to ensure “single-threaded” access to the world state. (The Clean designers eventually solved this problem through the use of “uniqueness types”)

The concept of monads seems to have been introduced (reused from other work) in later revisions of Haskell since it resulted in cleaner code (compared to continuations/streams):

The monadic approach rapidly dominated earlier models. The types are more compact, and more informative.


The best explanation I've seen is Simon Peyton-Jones' "Tackling the Awkward Squad."

From what I remember from the paper, issues around laziness played a big part in the decision. (I'm not sure if Clean is lazy by default the same way Haskell is.)

  • 5
    Clean is lazy too. May 21, 2012 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.