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.