Haskell IO
Purity
The trick is that once you threaded up functions explicitly using a second argument and returning a second value or implicitly, by hiding the second value behind an abstraction barrier, the referential transparency (property) will hold.
Same input and an initial value - same output, and a new “initial” value. These “ pairs” will always be the same, so expressions describing IO (to be performed eventually by runtime) are literally declarative expressions of a logic (describing parts of a pure state-machine).
This is how I/O
in Haskell is done. This is the meaning behind the
famous
type IO a = World -> (a,World)
IO a
uses the abstraction barrier aspect of a Monad
(so one cannot
see or touch the World).
In Haskell, but not in math, serialization is implicit in any monad because (>>=)
is
implemented using nested lambdas.
Notice that function composition (.)
is also nesting of lambdas.
This is not a coincidence - there is absolutely no other way to
enforce an order of evaluation in a Normal Order language. One has to
nest explicitly.
g . f = \x -> g (f x)
IO a
is similar to
type State s a = s -> (a, s)
In the case of IO a
the threading through (an enforced serialization) is
implicit, while with State s a
it is explicit within an ADT.
Yes, it is just an Abstract Data Type, which is also an instance of a Monad.
Just like [a]
.