CSci 450/503: Programming Languages

Top-Down Stepwise Refinement
Square Root Program

H. Conrad Cunningham

5 September 2017

Acknowledgements: These slides accompany section 2.5, “Using Top-Down Stepwise Refinement” from Chapter 2 “Basic Haskell Functional Programming” 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 August 2017 is a recent version of Firefox from Mozilla.

Code: The Haskell module for the Square root case study is in file Sqrt.hs. Limited testing code is in module TestSqrt.hs.

Using Top-Down Stepwise Refinement

Lecture Goals

Square Root Problem

Solution Strategy (1 of 2)

Top-down stepwise refinement – adapt general method to Haskell

Solution Strategy (2 of 2)

High-level Solution (1 of 2)

Postulate function with signature

    sqrtIter :: Double -> Double -> Double 

Encode Newton method step 2

    sqrtIter guess x 
        | goodEnough guess x = guess 
        | otherwise          = sqrtIter (improve guess x) x 

High-level Solution (2 of 2)

    sqrtIter guess x 
        | goodEnough guess x = guess 
        | otherwise          = sqrtIter (improve guess x) x 

Refinement: improve

Refine improve in Newton step 3

    improve :: Double -> Double -> Double
    improve guess x = average guess (x/guess)

Refinement: goodEnough

Refine goodEnough

Initial Guess

Sufficient just to use 1

    sqrt' :: Double -> Double
    sqrt' x | x >= 0 = sqrtIter 1 x

Making Haskell Module Sqrt.hs

    module Sqrt -- put in file "Sqrt.hs"
        (sqrt') -- only export sqrt', others hidden
    where

    sqrt' :: Double -> Double
    sqrt' x | x >= 0 = sqrt_iter 1 x

    sqrt_iter :: Double -> Double -> Double
    sqrt_iter guess x
        | good_enough guess x = guess
        | otherwise           = sqrt_iter (improve guess x) x

    good_enough :: Double -> Double -> Bool
    good_enough guess x = abs (square guess - x) < 0.001

    square :: Double -> Double
    square x = x * x

    average :: Double -> Double -> Double
    average x y = (x + y) / 2

    improve :: Double -> Double -> Double
    improve guess x = average guess (x/guess)

Using Haskell Module

Example use of Sqrt module (from Sqrt.hs)

    module TestSqrt
    where

    import Sqrt -- file Sqrt.hs, import all public features 

    main = do
        putStrLn (show (sqrt' 16))
        putStrLn (show (sqrt' 2))

Key Ideas

Code

The Haskell module for the Square root case study is in file Sqrt.hs. Limited testing code is in module TestSqrt.hs.