CSci 450/503: Programming Languages

Evaluation of Functional Programs

H. Conrad Cunningham

5 September 2017

Acknowledgements: These slides accompany section 3.2, “Evaluation of Functional Programs” from Chapter 3 “Evaluation and Efficiency”" of “Introduction to Functional Programming Using Haskell”.

Advisory: The HTML version of this document may require use of a browser that supports the display of MathML. A good choice as of September 2017 is a recent version of Firefox from Mozilla.

Evaluation of Functional Programs

Lecture Goals

Referential Transparency

Referential transparency:

A symbol (e.g., variable) always represents the same value within some well-defined context (e.g., function body)

Substitution (Reduction) Model

Redex:

a subexpression that can be reduced

Selecting Redexes (1)

By position in expression

Selecting Redexes (2)

By whether contained within another redex

Haskell uses leftmost outermost redex first

Function Example

    fact1 :: Int -> Int 
    fact1 n = if n == 0 then 
                  1 
              else 
                  n * fact1 (n-1) 

Leftmost Outermost Example (1)

fact1 2
\Longrightarrow { replace fact1 2 using definition }
if 2 == 0 then 1 else 2 * fact1 (2-1)
\Longrightarrow { evaluate 2 == 0 }
if False then 1 else 2 * fact1 (2-1)
\Longrightarrow { evaluate if }
2 * fact1 (2-1)
\Longrightarrow { replace fact1 (2-1) using definition, add implicit parentheses }
2 * (if (2-1) == 0 then 1 else (2-1) * fact1 ((2-1)-1))
\Longrightarrow { evaluate 2-1 in condition }

Leftmost Outermost Example (2)

2 * (if 1 == 0 then 1 else (2-1) * fact1 ((2-1)-1))
\Longrightarrow { evaluate 1 == 0 }
2 * (if False then 1 else (2-1) * fact1 ((2-1)-1))
\Longrightarrow { evaluate if }
2 * ((2-1) * fact1 ((2-1)-1))
\Longrightarrow { evaluate leftmost 2-1 }
2 * (1 * fact1 ((2-1)-1))
\Longrightarrow { replace fact1 ((2-1)-1) using definition, add implicit parentheses }
2 * (1 * (if ((2-1)-1) == 0 then 1
else ((2-1)-1) * fact1 ((2-1)-1)-1))
\Longrightarrow { evaluate 2-1 in condition }

Leftmost Outermost Example (3)

2 * (1 * (if (1-1) == 0 then 1
else ((2-1)-1) * fact1 ((2-1)-1)-1))
\Longrightarrow { evaluate 1-1 in condition }
2 * (1 * (if 0 == 0 then 1
else ((2-1)-1) * fact1 ((2-1)-1)-1))
\Longrightarrow { evaluate 0 == 0 }
2 * (1 * (if True then 1
else ((2-1)-1) * fact1 ((2-1)-1)-1))
\Longrightarrow { evaluate if }
2 * (1 * 1)
\Longrightarrow { evaluate 1 * 1 }

Leftmost Outermost Example (4)

2 * 1
\Longrightarrow { evaluate 2 * 1 }
2

String Reduction Model

2 * fact1 (2-1)
\Longrightarrow 2 * (if (2-1) == 0 then 1 else (2-1) * fact1 ((2-1)-1))

Graph Reduction Model

2 * fact1 (2-1)
\Longrightarrow 2 * (if (2-1) == 0 then 1 else (2-1) * fact1 ((2-1)-1))
\Longrightarrow 2 * (if 1 == 0 then 1 else 1 * fact1 (1)-1))

Lefmost Outermost Graph Reduction (1)

fact1 2
\Longrightarrow { replace fact1 2 using definition }
if 2 == 0 then 1 else 2 * fact1 (2-1)
\Longrightarrow { evaluate 2 == 0 in condition }
if False then 1 else 2 * fact1 (2-1) }
\Longrightarrow { evaluate if }
2 * fact1 (2-1)
\Longrightarrow { replace fact1 (2-1) using definition, add implicit parentheses }
2 * (if (2-1) == 0 then 1 else (2-1) * fact1 ((2-1)-1))
\Longrightarrow { evaluate 2-1 because of condition (3 occurrences in graph) }
2 * (if 1 == 0 then 1 else 1 * fact1 (1-1))
\Longrightarrow { evaluate 1 == 0 }

Lefmost Outermost Graph Reduction (2)

2 * (if False then 1 else 1 * fact1 (1-1))
\Longrightarrow { evaluate if }
2 * (1 * fact1 (1-1))
\Longrightarrow { replace fact1 ((1-1) using definition, add implicit parentheses }
2 * (1 * (if (1-1) == 0 then 1 else (1-1) * fact1 ((1-1)-1))
\Longrightarrow { evaluate 1-1 because of condition (3 occurrences in graph) }
2 * (1 * (if 0 == 0 then 1 else 0 * fact1 (0-1))
\Longrightarrow { evaluate 0 == 0 }
2 * (1 * (if True then 1 else 0 * fact1 (0-1))
\Longrightarrow { evaluate if }

Lefmost Outermost Graph Reduction (3)

2 * (1 * 1)
\Longrightarrow { evaluate 1 * 1 }
2 * 1
\Longrightarrow { evaluate 2 * 1 }
2

Time Complexity

Time measure:

number of steps in leftmost outermost graph reduction

Space Complexity

Space measure:

maximum graph size needed for leftmost outmost graph reduction

Termination

Precondition

Precondition:

Logical assertion that caller (client) must ensure holds before function call

Function fact1 n has precondition n >= 0 to prevent infinite recursion

Postcondition

Postcondition:

If precondition holds, then function must terminate with this logical assertion satisfied

Function fact1 has postcondition fact1 n = fact’(n) (defined in Chapter 2)

Function fact5

    fact5 :: Int -> Int 
    fact5 n = product [1..n]
    
Precondition – “weaker” than fact1

True

Postcondition – “stronger” than fact1

fact5 n = if n >= 0 then fact’(n) else 1

Invariant

Invariant (from Using Data Abstraction section):

Logical assertion that always holds for every “object” created by public constructors and manipulated only by public operations

Key Ideas

Code

The Haskell code for this chapter are in file EvalEff.hs.