Haskell puts all side effects in the
IO monad, which passes around the
RealWorld. This is unsatisfactory for a number of reasons, and Haskellers have spilled much ink on effects systems.
As I recently noted, there are
distinctions in how one handles effects at the logical level: in particular,
randomness is different from array writes.
In Haskell, the
IO type is defined as:
newtype IO a = IO (RealWorld -> (a, RealWorld))
One can imagine a monad for randomness which carries around the seed for a generator:
newtype Rand a = Rand (Seed -> (a, Seed))
These rhyme but there is a moral difference between
RealWorld cannot be duplicated (or discarded), while pseudorandom number generators split:
split : Seed -> (Seed, Seed)
In the language of Girard, this is object vs. object factory: a
an object, and a
Seed begets a
Intriguingly, Verse (a functional language) makes this distinction. Established functional programming languages lack facilities to handle linearity; there is a need to adopt modern ideas from logic in order to clarify various problems in the field.