liveBook · Manning

Referential transparency

As explained in Learn Haskell by Example

Referential transparency is the property that an expression can be replaced by the value it evaluates to without changing program behavior.

Referential transparency means replacing an expression with the value it evaluates to without changing program behavior. A pure function application has this property because its result depends only on its input. For correctness, the observable output matters even when two equivalent expressions differ in technical behavior or memory footprint. section 9.2.1 section 12.1.6

Replacing a pure expression

Given f x = x + 1, the expression f 1 always evaluates to 2. Replacing every occurrence of f 1 with 2 therefore preserves the program's result. This substitution does not apply to actions such as getLine, which depend on user input and other external effects. section 12.1.6

Pure code makes testing simpler: observing inputs and outputs is enough, and random tests need no artificial environment. A property can compare expressions with ==, as with the invariant that isMisc c equals the negation of isLower c, isUpper c, and isDigit c. section 9.2.1

Listing 9.15 Property test for checking predicate invariant
propIsMiscIsDefault :: IO ()
propIsMiscIsDefault =
  propertyTest
    (\c -> isMisc c == not
 (isLower c || isUpper c || isDigit c))  #1
    one  #2
    10000               #3

Property-test the predicate invariant across generated characters and repeated trials. section 9.2.1

Keep these boundaries in mind:

  • Treat pure function applications as replaceable by their results. section 9.2.1
  • Isolate input, file access, networking, and randomness in IO or other effect-handling structures. section 12.1.6
  • Do not assume every monad is referentially transparent; properties depend on the particular structure. section 12.1.6

How Learn Haskell by Example covers it

How deep it goes
Defines substitution, demonstrates it with f 1, and distinguishes observational equivalence from technical behavior.
Examples
Uses f 1 = 2, the isMisc predicate invariant, and IO actions such as getLine as contrasting examples.
What you can do after
Evaluate pure expressions by substitution and design property tests that compare equivalent outputs.
How it connects
Connects pure functions, property testing, monads, and the IO monad.

Also explained in

Compare how 9 books explain referential transparency →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.