Introduction Exercise 1 Debriefing Types Exercise Session 2 Formal Methods and Functional Programming http://www.infsec.ethz.ch/education/ss09/fmfp Patterns List induction List functions Introduction Exercise 1 Debriefing Types Patterns List induction List functions Schedule Exercise 1 Debriefing Type synonyms vs new data types Boolean expressions Bracketing Induction Types Patterns Lists Induction on lists Prelude list functions foldr and foldl Freitag, 20. Februar 2009 Functional Programming FS 2009 2 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Type synonyms > type Complex = (Float,Float) > re :: Complex -> Float > re (r,_) = r > im :: Complex -> Float > im (_,i) = i With this definition we can use Complex instead of (Float, Float) But: This does not define a new type! Freitag, 20. Februar 2009 Functional Programming FS 2009 3 Introduction Exercise 1 Debriefing Types Patterns List induction List functions New data types > data Complex = ComplexNumber Float Float > deriving (Eq, Show, Ord) > fromReal :: Float -> Complex > fromReal r = ComplexNumber r 0 > re' :: Complex -> Float > re' (ComplexNumber r i) = r > im' :: Complex -> Float > im' (ComplexNumber r i) = i Not just a synonym, but really a new data type! A value of type Complex' cannot be mistaken for a pair of floats (e.g. point coordinates)! Freitag, 20. Februar 2009 Functional Programming FS 2009 4 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Boolean expressions What can be done better in the following examples: > goodEnough x y > | abs (y^2 - x) < eps > | otherwise = True = False > goodEnough x y = if abs (y^2 - x) < eps then True else False Better: > goodEnough x y = abs (y^2 – x) < eps ... == True, ... == False, if ... then True else False Almost always “wrong” x == False <==> not x x /= y <==> x ‘xor’ y (if x, y booleans) Freitag, 20. Februar 2009 Functional Programming FS 2009 5 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Bracketing What is wrong here? mySqrt x y = if goodEnough x y then y else mySqrt x improve x y What Haskell does: mySqrt x y = if goodEnough x y then y else (mySqrt x improve) x y What (probably ☺) was intended: mySqrt x y = if goodEnough x y then y else mySqrt x (improve x y) Freitag, 20. Februar 2009 Functional Programming FS 2009 6 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction An induction proof consists of 1. The idea 2. The formal writeup! This course is not called Functional Programming and Formal Methods for nothing! Freitag, 20. Februar 2009 Functional Programming FS 2009 7 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof by induction on n Base case: n = 0 aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Step case: n => n + 1 aux (n+1) = next (aux n) -- (fE.3) = next (fibLouis n, fibLouis (n+1)) -- IH = (fibLouis (n+1), fibLouis n + fibLouis (n+1)) -- (fE.4) = (fibLouis (n+1), fibLouis (n+1+1)) -- (fL.3) qed. This solution is not so good. Why? Freitag, 20. Februar 2009 Functional Programming FS 2009 8 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof by induction on n Base case: n = 0 aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Step case: n => n + 1 ... Be precise: What do you want to prove? Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). ... Step Case: Show for every n:Nat. P(n) implies P(n+1) ... Alternatively: Base Case: Show aux 0 = (fibLouis 0, fibLouis 1) This leads to a lot more text... if being lazy is allowed, be lazy! Freitag, 20. Februar 2009 Functional Programming FS 2009 9 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Step Case: Show for every n:Nat. P(n) implies P(n+1) aux (n+1) = next (aux n) -- (fE.3) = next (fibLouis n, fibLouis (n+1)) -- IH = (fibLouis (n+1), fibLouis n + fibLouis (n+1)) -- (fE.4) = (fibLouis (n+1), fibLouis (n+1+1)) -- (fL.3) qed. Where is the next problem with this proof? Freitag, 20. Februar 2009 Functional Programming FS 2009 10 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) ... Never, never ever put the thing you want to prove on the first line of your proof and then apply steps on both sides! Freitag, 20. Februar 2009 Functional Programming FS 2009 11 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Never, never ever put the thing you want to prove on the first line of your proof and then apply steps on both sides! What could go wrong? Let’s prove 2=1! Oops! We define a := b 2 = 1 Multiply by (a^3 - a*(b + b*a) + b^2) on both sides: 2(a^3 - a*(b + b*a) + b^2) = 1(a^3 - a*(b + b*a) + b^2) Expand: 2a^3 - 2a*b - 2*a*b*a + 2*b^2 = a^3 – a*b - a*b*a + b^2 Subtract (a^3 – a*b – a*b*a + 2b^2): a^3 - a*b - a*b*a = -b^2 Apply a = b: b^3 - b^2 - b^3 = -b^2 Simplify: -b^2 = -b^2 qed? What went wrong here? Freitag, 20. Februar 2009 Functional Programming FS 2009 12 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Step Case: Show for every n:Nat. P(n) implies P(n+1) aux (n+1) = next (aux n) -- (fE.3) = next (fibLouis n, fibLouis (n+1)) -- IH = (fibLouis (n+1), fibLouis n + fibLouis (n+1)) -- (fE.4) = (fibLouis (n+1), fibLouis (n+1+1)) -- (fL.3) qed. Where is the next problem with this proof? Freitag, 20. Februar 2009 Functional Programming FS 2009 13 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Don’t do all steps at once! Only combine really trivial ones, when in doubt do a separate step What are (fE.2), Freitag, 20. Februar 2009 (fL.1) and (fL.2) ??? Functional Programming FS 2009 14 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction First define which definition is which! > > > > fibLouis fibLouis fibLouis fibLouis :: Int -> Int 0 = 0 1 = 1 n = fibLouis (n-1) + fibLouis (n-2) > fibEva :: Int -> Int > fibEva n = fst (aux n) > where aux 0 = (0,1) > aux n = next (aux (n-1)) > next (a,b) = (b, a+b) Freitag, 20. Februar 2009 Functional Programming FS 2009 -- fibLouis.1 -- fibLouis.2 -- fibLouis.3 ----- fibEva.1 aux.1 aux.2 next.1 15 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (fibLouis 0, fibLouis 1) (0,1) = (0,1) -- because of (fE.2), (fL.1) and (fL.2) Step Case: Show for every n:Nat. P(n) implies P(n+1) aux (n+1) = next (aux n) -- (fE.3) = next (fibLouis n, fibLouis (n+1)) -- IH = (fibLouis (n+1), fibLouis n + fibLouis (n+1)) -- (fE.4) = (fibLouis (n+1), fibLouis (n+1+1)) -- (fL.3) qed. How does fiblouis n = fibLouis (n-1) + fibLouis (n-2) apply to fibLouis n + fibLouis (n+1) ? Needs arithmetic transformation first: fibLouis n + fibLouis (n+1) = fibLouis (n+2-1) + fibLouis (n+2-2) Freitag, 20. Februar 2009 Functional Programming FS 2009 16 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction Lemma 1: FORALL n: Nat aux n = (fibLouis n, fibLouis (n+1)) -------Proof: Let P(n) := (aux n = (fibLouis n, fibLouis (n+1))) We show that FORALL n:Nat. P(n) by induction Base Case: Show P(0). aux 0 = (0,1) = (fibLouis 0, fibLouis 1) -- aux.1 -- fibLouis.1, fibLouis.2 Step Case: Show for every n:Nat. P(n) implies P(n+1) aux (n+1) = next (aux n) = next (fibLouis n, fibLouis (n+1)) = (fibLouis (n+1), fibLouis n + fibLouis (n+1)) = (fibLouis (n+1), fibLouis (n+2-1) + fibLouis (n+2-2) = (fibLouis (n+1), fibLouis (n+2)) ------ aux.2 IH next.1 arith rev. fibLouis.3 qed. Freitag, 20. Februar 2009 Functional Programming FS 2009 17 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction What about this: > > where aux 0 = (0,1) aux n = next (aux (n-1)) aux (n+1) = next (aux n) -- aux.1 -- aux.2 -- aux.2 Does aux.2 really apply here? What about aux.1? Have to prove n+1 > 0 … which is easy since we know: n:Nat. and therefore n >= 0 One last thing: > fibLouis 0 = 0 > fibLouis 1 = 1 > fibLouis n = fibLouis (n-1) + fibLouis (n-2) -- fibLouis.1 -- fibLouis.2 -- fibLouis.3 (fibLouis (n+1), fibLouis (n+2-1) + fibLouis (n+2-2) = (fibLouis (n+1), fibLouis (n+2)) -- arith -- rev. fibLouis.3 n has to be greater than 1 for fibLouis.3 to apply. n+2 is always greater than 1 for n:Nat. Freitag, 20. Februar 2009 Functional Programming FS 2009 18 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Types in Haskell Types are constructed from base types and type constructors Base types: Bool, Int, Char, … Type contructor: builds a more complex type from simpler types Tuple type constructor: T1, T2, …, Tn List type constructor: T [T] (T1, T2, …, Tn) Examples: (Bool, Int) [(Bool, Int)] ([(Bool, Int)], Bool) … Freitag, 20. Februar 2009 Functional Programming FS 2009 19 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Type versus data constructors From type constructors you have to differentiate data constructors: Type constructors build types Data constructors build values (expressions) Examples for data constructors: For Type Int: 0, 1, 2, … For Type Char: ‘a’, ‘b’, ‘c’, … For Type Bool: True, False Note: Data constructors are always upper case! Lists: Two data constructors exist: [] (pronounce: “nil”) builds an empty list (:) (pronounce: “cons”) builds a bigger list from a given element and a list 1 : (2 : []) :: [Int] Freitag, 20. Februar 2009 Functional Programming FS 2009 20 Introduction Exercise 1 Debriefing Types Patterns List induction List functions For the example before: > data Complex = ComplexNumber Float Float > deriving (Eq, Show, Ord) > fromReal :: Float -> Complex > fromReal r = ComplexNumber r 0 > re' :: Complex -> Float > re' (ComplexNumber r i) = r > im' :: Complex -> Float > im' (ComplexNumber r i) = I Type constructor Data constructor Freitag, 20. Februar 2009 Functional Programming FS 2009 21 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Type versus data constructors Note: the data constructor “cons” is not a constant (like the data constructors 0, 'a', True, [],…) but a function: (:) :: Int -> [Int] -> [Int] Convenient syntactic sugar: [1,2,3] shorthand for 1:(2:(3:[])) (for any element type) “hello” shorthand for 'h':'e':'l':'l':'o':[] (for Char element type only) Difference between lists and tuples Tuples have fixed length, but different types for fields are possible e.g. (1, True, 'a') Lists have variable length with one single element type e.g. [1,2,3] Freitag, 20. Februar 2009 Functional Programming FS 2009 22 Introduction Exercise 1 Debriefing Types Patterns Exercise: Pattern matching List induction List functions Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction proofs on lists Similar to induction on natural numbers Prove FORALL l :: [a] . P(l) Base case Show P([]) Step case Show for all x::a, xs::[a] that P(xs) implies P(x:xs) P(xs) is the induction hypothesis (IH) Freitag, 20. Februar 2009 Functional Programming FS 2009 24 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Induction proofs on lists In the proof about the one-time pad you have to do induction simultaneously over two lists of the same length. The standard induction scheme for lists is not very convenient in these cases. In order to prove a statement of the following form: FORALL xs::[a], ys::[a]. length xs = length ys => P(xs,ys) It suffices to prove that these two cases hold: Base Case: P([], []) Step Case: FORALL x::a, xs::[a], y::a, ys::[a]. P(xs,ys) => P(x:xs, y:ys) If you wonder how this can be derived: See additional notes on webpage for hints & try to derive it yourself Freitag, 20. Februar 2009 Functional Programming FS 2009 25 Introduction Exercise 1 Debriefing Types Patterns List induction List functions Training: List functions from the Haskell Prelude Higher-order functions Lambda expressions For more list functions, see either the Prelude or the additional notes on the webpage Introduction Exercise 1 Debriefing Types Patterns List induction List functions List functions: foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldr, applied to a binary operator f, a starting value (typically the right identity of the operator) z and a list [x1, x2, ..., xn] reduces the list using the binary operator, from right to left: foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...) Infix notation of binary functions: f x y can be written as x `f` y Useful for predicates like ∈: x `elem` xs instead of elem x xs Can also be done the other way round: 1 + 2 can be written as (+) 1 2 Freitag, 20. Februar 2009 Functional Programming FS 2009 27 Introduction Exercise 1 Debriefing Types Patterns List induction List functions List functions: foldl foldl :: (a -> b -> a) -> a -> [b] -> a foldl, applied to a binary operator f, a starting value (typically the left identity of the operator) z and a list [x1, x2, …, xn] reduces the list using the binary operator, from left to right. foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn Example: > foldMax xs = foldl f 0 xs where > f :: Int -> Int -> Int > f x y = max x y Freitag, 20. Februar 2009 Functional Programming FS 2009 28