Monads for effects are familiar to the Haskell programmer; they were introduced by Wadler's "Monads for functional programming" and are the accepted way to work with side effects in a lazy language.

Note that corralling side effects is *necessary* with laziness:
sharing gives us efficient evaluation, but if sharing a side-effecting result may change how often its effects are performed.

Wadler's approach was brilliant and timely. Nearly all I/O in a typical Haskell program is done via the monadic interface. This is why monads are famously associated with Haskell: it is hard to imagine doing I/O in a lazy language without reinventing the monad.

Nevertheless, there remain some practical limitations to Haskell's `IO`

type.

# Laziness & Streaming FFI

There are several unsatisfying tidbits w.r.t. C FFI:

The

`unsafePerformIO`

function is justified, for instance, to compute \( {n \choose k } \). We need to free memory allocated during computation; however, the result is constant and can be shared. There is no need to perform its effects each time as there would be with`putStrLn`

, for instance.The requirements here are idiosyncratic: one must perform

*all*clumped effects together or not at all, and one can reuse the result without performing the effects again.As I have pointed out before, one would like to wrap a streaming C FFI and provide a streaming API based on laziness. In such situations, one would use

`unsafeIOToST`

or`unsafeInterleaveIO`

.The requirements here are different: one would like to stream

`ByteString`

s, with allocations (a side effect) occuring only as-needed, based on forcing lazy values. Again, effects need to be clumped together.However,

`unsafeInterleaveIO`

is pathological. However, it is now the only way to wrap a C API with a Haskell API that would be the same as something written in pure Haskell.

# Philosophical Foundations

There are some philosophical objections to Haskell's
IO type:
As pointed out by Wadler in Linear types can change the world!,
one can duplicate or discard the `RealWorld`

:

kill : RealWorld -> ()

dupl : RealWorld -> (RealWorld, RealWorld)

Moreover, it is not clear that all effecting functions need take place in the
`IO`

monad: perhaps one could use a `CFFI`

token for interacting with an
appropriate C API (say, for streaming decompression) and another for console
output.

# Confusion

## mtl-Replacements

Some Haskell libraries (and even academic papers) claim to offer "effects" - but are really more like mtl replacements.

None address the C FFI cases above, and in any case GHC still only accepts FFI
bindings through `IO`

.

## Algebraic Effects

Some languages (ATS, Kitten, Mirth, Idris, PureScript) track effects at the type level, but they do not inform the above problems around laziness. ATS does not require a token to be passed around for effects and does not use monads at all.