# Referential transparency

A key advantage to pure functional programming is the property of referential transparency, ﬁrst enunciated by Quine and deﬁned by him as follows:

“I call a mode of containment φ referentially transparent if, whenever an occurrence of a singular term t is purely referential in a term or sentence ψ(t), it is purely referential also in the containing term or sentence φ(ψ(t))”.

In formalizing this idea for programming languages, Søndergaard and Sestoft conclude by saying informally,

“[A]n operator is referentially transparent if it preserves applicability of Leibniz’s law, or substitutivity of identity: the principle that any subexpression can be replaced by any other equal in value.”

Derek Bronish.

...with the term first being introduced to the study of programming languages by Christopher Strachey:

One of the most useful properties of expressions is that called by Quine referential transparency. In essence this means that if we wish to find the value of an expression which contains a sub-expression, the only thing we need to know about the sub-expression is its value. Any other features of the sub-expression, such as its internal structure, the number and nature of its components, the order in which they are evaluated or the colour of the ink in which they are written, are irrelevant to the value of the main expression.

Side effects like (uncontrolled) imperative update break this desirable property. C and ML are languages with constructs that are not referentially transparent.

As an example, consider the following program in ML:

``` puts "h"; puts "a"; puts "h"; puts "a"
```

which prints `"haha"`. In an attempt to factor out the repetition, we write

```let val x = (puts "h"; puts "a")
in  x; x end
```

but now the laugh is on us, because `"ha"` is only printed once. The reason is that `puts`'s side effect is only realized when `x` gets bound, so we should have written

```let fun x () = (puts "h"; puts "a")
in  x (); x () end
```

Haskell's monadic I/O system distinguishes between values and actions like the `puts` procedure above. So we do indeed have that

```putStr "h" >> putStr "a" >> putStr "h" >> putStr "a"
```

is equivalent to

```let x = putStr "h" >> putStr "a"
in  x >> x
```

: