Haskell: The Craft of Functional Programming Simon Thompson (c) Addison-Wesley, 1999. Chapter 8 Reasoning about programs ^^^^^^^^^^^^^^^^^^^^^^^^ > module Chapter8 where > import Prelude hiding (sum,length,(++),reverse,unzip) Testing and verification ^^^^^^^^^^^^^^^^^^^^^^^^ A function supposed to give the maximum of three (integer) values. > mysteryMax :: Int -> Int -> Int -> Int > mysteryMax x y z > | x > y && x > z = x > | y > x && y > z = y > | otherwise = z Definedness and termination ^^^^^^^^^^^^^^^^^^^^^^^^^^^ A factorial function, giving an undefined result on negative integers. > fact :: Int -> Int > fact n > | n==0 = 1 > | otherwise = n * fact (n-1) An infinite list > posInts :: [Int] > posInts = [1, 2 .. ] Induction ^^^^^^^^^ The sum function, defined recursively. > sum :: [Int] -> Int > sum [] = 0 -- (sum.1) > sum (x:xs) = x + sum xs -- (sum.2) Double every element of an integer list. > doubleAll :: [Int] -> [Int] > doubleAll [] = [] -- (doubleAll.1) > doubleAll (z:zs) = 2*z : doubleAll zs -- (doubleAll.2) The property linking the two: sum (doubleAll xs) = 2 * sum xs -- (sum+dblAll) Other functions used in the examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The definitions given here use explicit recursion, rather than applying higher-order functions as may happen in the Prelude definitions. > length :: [a] -> Int > length [] = 0 -- (length.1) > length (z:zs) = 1 + length zs -- (length.2) > (++) :: [a] -> [a] -> [a] > [] ++ zs = zs -- (++.1) > (w:ws) ++ zs = w:(ws++zs) -- (++.2) > reverse :: [a] -> [a] > reverse [] = [] -- (reverse.1) > reverse (z:zs) = reverse zs ++ [z] -- (reverse.2) > unzip :: [(a,b)] -> ([a],[b]) > unzip [] = ([],[]) > unzip ((x,y):ps) > = (x:xs,y:ys) > where > (xs,ys) = unzip ps Generalizing the proof goal ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The shunting function > shunt :: [a] -> [a] -> [a] > shunt [] ys = ys -- (shunt.1) > shunt (x:xs) ys = shunt xs (x:ys) -- (shunt.2) > rev :: [a] -> [a] > rev xs = shunt xs [] -- (rev.1) An alternative definition of the factorial function. > fac2 :: Int -> Int > fac2 n = facAux n 1 > facAux :: Int -> Int -> Int > facAux 0 p = p > facAux n p = facAux (n-1) (n*p)