Difference between revisions of "Referential transparency"

From HaskellWiki
Jump to navigation Jump to search
(Various sections rewritten or reorganised)
m
Line 1: Line 1:
 
[[Category:Glossary]]
 
[[Category:Glossary]]
Referential transparency is an oft-touted property of (pure) functional languages, which makes it easier to reason about the behavior of programs. While there is no single formal definition[[#notes|[1]]], it usually means that an expression always evaluates to the same result in any context. Side effects like (uncontrolled) imperative update break this desirable property. C and ML are languages with constructs that are not referentially transparent.
+
Referential transparency is an oft-touted property of ([[Pure|pure]]) functional languages, which makes it easier to reason about the behavior of programs. While there is no single formal definition[[#notes|[1]]], it usually means that an expression always evaluates to the same result in any context. 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[[#notes|[2][3]]] in Standard ML:
 
As an example, consider the following program[[#notes|[2][3]]] in Standard ML:
Line 39: Line 39:
 
[4] There is some debate about whether the imprecisely-defined semantics of <code>Int</code> breaks referential transparency. For instance, <code>even (maxBound :: Int)</code> may be <code>True</code> in some contexts and <code>False</code> in others. Another example is <code>System.Info.os :: String</code>.
 
[4] There is some debate about whether the imprecisely-defined semantics of <code>Int</code> breaks referential transparency. For instance, <code>even (maxBound :: Int)</code> may be <code>True</code> in some contexts and <code>False</code> in others. Another example is <code>System.Info.os :: String</code>.
   
One perspective is that Haskell is not just one language (plus <code>Prelude</code>), but a family of languages, parameterized by a collection of implementation-dependent parameters.
+
[5] One perspective is that Haskell is not just one language (plus <code>Prelude</code>), but a family of languages, parameterized by a collection of implementation-dependent parameters.
 
Each such language is referentially transparent, even if the collection as a whole might not be.
 
Each such language is referentially transparent, even if the collection as a whole might not be.
 
Some people are satisfied with this situation and others are not.
 
Some people are satisfied with this situation and others are not.

Revision as of 22:32, 5 November 2021

Referential transparency is an oft-touted property of (pure) functional languages, which makes it easier to reason about the behavior of programs. While there is no single formal definition[1], it usually means that an expression always evaluates to the same result in any context. 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[2][3] in Standard 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

Notes:

[1] Wolfram Kahl provides a USENET post by Tom DeBoni containing a summary of various definitions for referential transparency.

[2] This example is based on one from pages 4-5 of 33, in Philip Wadler's How to Declare an Imperative, ACM Computing Surveys, 29(3):240--263, September 1997.

[3] where puts can be defined as fun puts s = TextIO.output(TextIO.stdOut, s);

[4] There is some debate about whether the imprecisely-defined semantics of Int breaks referential transparency. For instance, even (maxBound :: Int) may be True in some contexts and False in others. Another example is System.Info.os :: String.

[5] One perspective is that Haskell is not just one language (plus Prelude), but a family of languages, parameterized by a collection of implementation-dependent parameters. Each such language is referentially transparent, even if the collection as a whole might not be. Some people are satisfied with this situation and others are not.