[Haskell-cafe] Referential Transparency and Monads

Jonathan Cast jonathanccast at fastmail.fm
Thu Apr 9 15:14:24 EDT 2009

On Thu, 2009-04-09 at 12:31 -0400, Brandon S. Allbery KF8NH wrote:
> On 2009 Apr 9, at 11:47, Mark Spezzano wrote:
> > How exactly do monads “solve” the problem of referential
> > transparency? I understand RT to be such that a function can be
> > replaced with a actual value.
> >  
> > Since a monad could potentially encapsulate any other value—say,
> > data read from a keyboard—doesn’t that violate the assumption of RT
> > on monads?

> Monads provide a way to carry extra data or operations around with
> their values.  IO passes an opaque "world state" around in the
> background, conceptually I/O operations modify the "world state" and
> it is in fact always valid to replace the monadified version with the
> unwrapped version --- ignoring IORefs, IO is just a simple state
> monad.

I'm not sure what you mean by that, but semantically IO is definitely
*not* a state monad.  Under any circumstances or any set of assumptions.

GHC *implements* IO as a state monad, but not because it semantically
is.  Rather, GHC's back-end language (STG) is an *impure* lazy
functional language, supplying primitive functions with (ultimate)
result type

    (# State# s, alpha #)

, for some alpha,[1] that are side-effectful.  The intention is that the
State# s component (which has almost no run-time representation) is used
to ensure a strict sequencing of the evaluation of these expressions ---
which intention can be violated by using the operations unsafePerformIO
and unsafeInterleaveIO --- allowing the language to be both
side-effectful and lazy without the programmer necessarily effectively
losing the ability to control what the outcome of running the program
will be.

But that has nothing to do with referential transparency, because the
language those tricks are used in is not referentially transparent.
It's just an implementation technique for implementing a referentially
transparent source language on a non-referentially transparent
imperative stored-memory computer.


[1] As pointed out in another thread a couple of weeks ago, the order of
these components is reversed: they should be

    (# alpha, State# s #)

It's probably too late to change it now, though.

More information about the Haskell-Cafe mailing list