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








