1 Static Contract Checking for Haskell Dana N. Xu University of Cambridge Joint work with Simon Peyton Jones Microsoft Research Cambridge Koen Claessen.

Slides:



Advertisements
Similar presentations
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Advertisements

Static Contract Checking for Haskell Dana N. Xu University of Cambridge Ph.D. Supervisor: Simon Peyton Jones Microsoft Research Cambridge.
An Abstract Interpretation Framework for Refactoring P. Cousot, NYU, ENS, CNRS, INRIA R. Cousot, ENS, CNRS, INRIA F. Logozzo, M. Barnett, Microsoft Research.
CS 267: Automated Verification Lecture 8: Automata Theoretic Model Checking Instructor: Tevfik Bultan.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
Extended Static Checking for Haskell (ESC/Haskell) Dana N. Xu University of Cambridge advised by Simon Peyton Jones Microsoft Research, Cambridge.
TOWARDS A FINITE MODEL THEORY FOR HIGHER-ORDER PROGRAM VERIFICATION Dimitrios Vytiniotis, Koen Claessen, Simon Peyton Jones, Dan Rosén WG2.8 – Annapolis,
Higher-Order Functions Koen Lindström Claessen. What is a “Higher Order” Function? A function which takes another function as a parameter. Examples map.
0 PROGRAMMING IN HASKELL Chapter 6 - Recursive Functions Most of this should be review for you.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
PSUCS322 HM 1 Languages and Compiler Design II Formal Semantics Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU Spring.
MinML: an idealized programming language CS 510 David Walker.
Sparkle A theorem prover for the functional language Clean Maarten de Mol University of Nijmegen February 2002.
Dec Formal Semantics1 Programming Language Theory Formal Semantics Leif Grönqvist The national Graduate School of Language Technology (GSLT) MSI.
Well-cooked Spaghetti: Weakest-Precondition of Unstructured Programs Mike Barnett and Rustan Leino Microsoft Research Redmond, WA, USA.
Type Inference: CIS Seminar, 11/3/2009 Type inference: Inside the Type Checker. A presentation by: Daniel Tuck.
Simon Peyton Jones Microsoft Research Joint work with Dana Xu, University of Cambridge Dec 2007.
Cse536 Functional Programming 1 7/14/2015 Lecture #2, Sept 29, 2004 Reading Assignments –Begin Chapter 2 of the Text Home work #1 can be found on the webpage,
Cormac Flanagan University of California, Santa Cruz Hybrid Type Checking.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
1 Static Contract Checking for Haskell Dana N. Xu INRIA France Work done at University of Cambridge Joint work with Simon Peyton Jones Microsoft Research.
0 REVIEW OF HASKELL A lightening tour in 45 minutes.
0 PROGRAMMING IN HASKELL Chapter 7 - Defining Functions, List Comprehensions.
Type Systems CS Definitions Program analysis Discovering facts about programs. Dynamic analysis Program analysis by using program executions.
CS 363 Comparative Programming Languages Semantics.
Sound Haskell Dana N. Xu University of Cambridge Joint work with Simon Peyton Jones Microsoft Research Cambridge Koen Claessen Chalmers University of Technology.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
1-Nov-15 Haskell II Functions and patterns. Data Types Int + - * / ^ even odd Float + - * / ^ sin cos pi truncate Char ord chr isSpace isUpper … Bool.
0 PROGRAMMING IN HASKELL Chapter 9 - Higher-Order Functions, Functional Parsers.
11/1/20151 GC16/3011 Functional Programming Lecture 5 Miranda patterns, functions, recursion and lists.
Overview of the Haskell 98 Programming Language
CS5205Haskell1 CS5205: Foundations in Programming Languages FP with Haskell A pure lazy functional language that embodies many innovative ideas in language.
Semantics In Text: Chapter 3.
0 Odds and Ends in Haskell: Folding, I/O, and Functors Adapted from material by Miran Lipovaca.
COP4020 Programming Languages Introduction to Axiomatic Semantics Prof. Robert van Engelen.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Advanced Formal Methods Lecture 3: Simply Typed Lambda calculus Mads Dam KTH/CSC Course 2D1453, Some material from B. Pierce: TAPL + some from.
Types and Programming Languages Lecture 11 Simon Gay Department of Computing Science University of Glasgow 2006/07.
CMSC 330: Organization of Programming Languages Operational Semantics a.k.a. “WTF is Project 4, Part 3?”
Recursion on Lists Lecture 5, Programmeringsteknik del A.
Kyung-Goo Doh Hanyang University - ERICAComputer Science & Engineering Functional Programming / Imperative Programming CSE215 Fundamentals of Program Design.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: More on Functions and List Comprehensions Dr. Hyunyoung Lee.
CMSC 330: Organization of Programming Languages Lambda Calculus and Types.
Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture:
1 Static Contract Checking for Haskell Dana N. Xu University of Cambridge Joint work with Simon Peyton Jones Microsoft Research Cambridge Koen Claessen.
Static Techniques for V&V. Hierarchy of V&V techniques Static Analysis V&V Dynamic Techniques Model Checking Simulation Symbolic Execution Testing Informal.
C SC 573 Theory of Computation Theory of Computation Lecture 05 Reduction.
Types and Programming Languages Lecture 14 Simon Gay Department of Computing Science University of Glasgow 2006/07.
CS357 Lecture 13: Symbolic model checking without BDDs Alex Aiken David Dill 1.
CIS 540 Principles of Embedded Computation Spring Instructor: Rajeev Alur
0 PROGRAMMING IN HASKELL Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and a few other sources) Odds and Ends,
CMSC 330: Organization of Programming Languages Operational Semantics.
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
An introduction to functional programming using Haskell CENG242 –Recitation 1.
6-Jul-16 Haskell II Functions and patterns. Data Types Int + - * / ^ even odd Float + - * / ^ sin cos pi truncate Char ord chr isSpace isUpper … Bool.
Functional Programming
Types CSCE 314 Spring 2016.
A lightening tour in 45 minutes
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Extended Static Checking for Haskell (ESC/Haskell)
PROGRAMMING IN HASKELL
Python Tutorial for C Programmer Boontee Kruatrachue Kritawan Siriboon
CSCE 314: Programming Languages Dr. Dylan Shell
PROGRAMMING IN HASKELL
Static Contract Checking for Haskell
Presentation transcript:

1 Static Contract Checking for Haskell Dana N. Xu University of Cambridge Joint work with Simon Peyton Jones Microsoft Research Cambridge Koen Claessen Chalmers University of Technology

2 Module UserPgm where f :: [Int] -> Int f xs = head xs `max` 0 : … f [] … Program Errors Give Headache! Glasgow Haskell Compiler (GHC) gives at run-time Exception: Prelude.head: empty list Module Prelude where head :: [a] -> a head (x:xs) = x head [] = error “empty list”

Types, Contracts, Definition inc :: Int -> Int inc 2 {x | x > 0} -> {r | r > x} inc x = x + 1 contract Type Definition

4 Bugs head (x:xs) = x head :: [Int] -> Int …(head 1)… head 2 {xs | not (null xs)} -> {r | True} …(head [])… Bug! Contract (original Haskell boolean expression) Type not :: Bool -> Bool not True = False not False = True null :: [a] -> Bool null [] = True null (x:xs) = False

5 Contract Checking head 2 {xs | not (null xs)} -> {r | True} head (x:xs’) = x f xs = head xs `max` 0 Warning: f [] calls head which may fail head’s precondition! f_ok xs = if null xs then 0 else head xs `max` 0 No more warnings from the compiler!

6 Satisfying a Predicate Contract e 2 {x | p} if (1) p[e/x] gives True and (2) e is crash-free. Arbitrary boolean-valued Haskell expression Recursive function, higher-order function, partial function can be called!

7 Expressiveness of the Specification Language data T = T1 Bool | T2 Int | T3 T T sumT :: T -> Int sumT 2 {x | noT1 x} -> {r | True} sumT (T2 a) = a sumT (T3 t1 t2) = sumT t1 + sumT t2 noT1 :: T -> Bool noT1 (T1 _) = False noT1 (T2 _) = True noT1 (T3 t1 t2) = noT1 t1 && noT1 t2

8 Expressiveness of the Specification Language sumT :: T -> Int sumT 2 {x | noT1 x} -> {r | True} sumT (T2 a) = a sumT (T3 t1 t2) = sumT t1 + sumT t2 rmT1 :: T -> T rmT1 2 {x | True} -> {r | noT1 r} rmT1 (T1 a) = if a then T2 1 else T2 0 rmT1 (T2 a) = T2 a rmT1 (T3 t1 t2) = T3 (rmT1 t1) (rmT1 t2) For all crash-free t::T, sumT (rmT1 t) will not crash.

9 Higher Order Functions all :: (a -> Bool) -> [a] -> Bool all f [] = True all f (x:xs) = f x && all f xs filter :: (a -> Bool) -> [a] -> [a] filter 2 {f | True} -> {xs | True} -> {r | all f r} filter f [] = [] filter f (x:xs’) = case (f x) of True -> x : filter f xs’ False -> filter f xs’

10 Contracts for Higher-order Function’s Parameter f1 :: (Int -> Int) -> Int f1 2 ({x | True} -> {y | y >= 0}) -> {r | r >= 0} f1 g = (g 1) - 1 f2 :: {r | True} f2 = f1 (\x -> x – 1) Error: f1’s postcondition fails when (g 1) >= 0 holds (g 1) – 1 >= 0 does not hold Error: f2 calls f1 which fails f1’s precondition [Findler&Felleisen:ICFP’02, Blume&McAllester:ICFP’04]

11 Various Examples zip :: [a] -> [b] -> [(a,b)] zip 2 {xs | True} -> {ys | sameLen xs ys} -> {rs | sameLen rs xs } sameLen [] [] = True sameLen (x:xs) (y:ys) = sameLen xs ys sameLen _ _ = False f91 :: Int -> Int f91 2 { n {r | r == 91 } f91 n = case (n <= 100) of True -> f91 (f91 (n + 11)) False -> n – 10

12 Sorting sorted [] = True sorted (x:[]) = True sorted (x:y:xs) = x <= y && sorted (y : xs) insert :: Int -> [Int] -> [Int] insert 2 {i | True} -> {xs | sorted xs} -> {r | sorted r} merge :: [Int] -> [Int] -> [Int] merge 2 {xs | sorted xs}->{ys | sorted ys}->{r | sorted r} bubbleHelper :: [Int] -> ([Int], Bool) bubbleHelper 2 {xs | True} -> {r | not (snd r) ==> sorted (fst r)} insertsort, mergesort, bubblesort 2 {xs | True} -> {r | sorted r} (==>) True x = x (==>) False x = True

AVL Tree balanced :: AVL -> Bool balanced L = True balanced (N t u) = balanced t && balanced u && abs (depth t - depth u) <= 1 data AVL = L | N Int AVL AVL insert, delete :: AVL -> Int -> AVL insert 2 {x | balanced x} -> {y | True} -> {r | notLeaf r && balanced r && 0 <= depth r - depth x && depth r - depth x <= 1 } delete 2 {x | balanced x} -> {y | True} -> {r | balanced r && 0 <= depth x - depth r && depth x - depth r <= 1} (&&) True x = x (&&) False x = False

14 Functions without Contracts data T = T1 Bool | T2 Int | T3 T T noT1 :: T -> Bool noT1 (T1 _) = False noT1 (T2 _) = True noT1 (T3 t1 t2) = noT1 t1 && noT1 t2 (&&) True x = x (&&) False x = False No abstraction is more compact than the function definition itself!

15 Contract Synonym contract Ok = {x | True} contract NonNull = {x | not (null x)} head :: [Int] -> Int head 2 NonNull -> Ok head (x:xs) = x {-# contract Ok = {x | True} -#} {-# contract NonNull = {x | not (null x)} #-} {-# contract head :: NonNull -> Ok #-} Actual Syntax

Lots of Questions  What does “crash” mean?  What is “a contract”?  What does it mean to “satisfy a contract”?  How can we verify that a function does satisfy a contract?  What if the contract itself diverges? Or crashes? It’s time to get precise... 16

What is the Language?  Programmer sees Haskell  Translated (by GHC) into Core language Lambda calculus Plus algebraic data types, and case expressions BAD and UNR are (exceptional) values Standard reduction semantics e 1 ! e 2 17

18 Two Exceptional Values  BAD is an expression that crashes. error :: String -> a error s = BAD head (x:xs) = x head [] = BAD  UNR (short for “unreachable”) is an expression that gets stuck. This is not a crash, although execution comes to a halt without delivering a result. (identifiable infinite loop) div x y = case y == 0 of True -> error “divide by zero” False -> x / y head (x:xs) = x Real Haskell Program

Crashing Definition (Crash). A closed term e crashes iff e ! * BAD Definition (Crash-free Expression) An expression e is crash-free iff 8 C. BAD 2 s C, ` C[[e]] :: (), C[[e]] ! * BAD Non-termination is not a crash (i.e. partial correctness).

Crash-free Examples Lemma: For all closed e, e is syntactically safe ) e is crash-free. Crash-free? BAD NO (1,BAD)NO (1, True)YES \x -> BAD NO \x -> x YES \x -> (BAD, x) NO \x -> if x >= 0 then x + 1 else BAD NO \x -> if x*x >= 0 then x + 1 else BAD Hmm.. YES

21 What is a Contract (related to [Findler:ICFP02,Blume:ICFP04,Hinze:FLOPS06,Flanagan:POPL06]) Full version: x’:{x | x >0} -> {r | r > x’} Short hand: {x | x > 0} -> {r | r > x} k:({x | x > 0} -> {y | y > 0}) -> {r | r > k 5} t 2 Contract t ::= {x | p} Predicate Contract | x:t 1 ! t 2 Dependent Function Contract | (t 1, t 2 ) Tuple Contract | Any Polymorphic Any Contract

22 Questions on e 2 t 3 2 {x | x > 0} 5 2 {x | True} (True, 2) 2 {x | (snd x) > 0} ? (head [], 3) 2 {x | (snd x) > 0} ? BAD 2 ? ? 2 {x | False} ? 2 {x | BAD} \x-> BAD 2 {x | False} -> {r | True} ? \x-> BAD 2 {x | True} -> ? \x-> x 2 {x | True} ?

23 What exactly does it mean to say that e “satisfies” contract t? e 2 t

24 Contract Satisfaction (related to [Findler:ICFP02,Blume:ICFP04,Hinze:FLOPS06]) e " means e diverges or e ! * UNR e 2 {x | p}, e " or (e is crash-free and p[e/x] ! * {BAD, False} [A1] e 2 x:t 1 ! t 2, 8 e 1 2 t 1. (e e 1 ) 2 t 2 [e 1 /x] [A2] e 2 (t 1, t 2 ), e " or (e ! * (e 1,e 2 ) and [A3] e 1 2 t 1 and e 2 2 t 2 ) e 2 Any, True [A4] Given ` e ::  and ` c t :: , we define e 2 t as follows:

Only Crash-free Expression Satisfies a Predicate Contract e 2 {x | p}, e " or (e is crash-free and p[e/x] ! * {BAD, False} e 2 x:t 1 ! t 2, 8 e 1 2 t 1. (e e 1 ) 2 t 2 [e 1 /x] e 2 (t 1, t 2 ), e " or (e ! * (e 1,e 2 ) and e 1 2 t 1 and e 2 2 t 2 ) e 2 Any, True YES or NO? (True, 2) 2 {x | (snd x) > 0} YES (head [], 3) 2 {x | (snd x) > 0} NO \x-> x 2 {x | True} YES \x-> x 2 {x | loop} YES 5 2 {x | BAD} NO loop 2 {x | False} YES loop 2 {x | BAD} YES

26 All Expressions Satisfy Any fst 2 ({x | True}, Any) -> {r | True} fst (a,b) = a g x = fst (x, BAD) YES or NO? 5 2 Any YES BAD 2 Any YES (head [], 3) 2 ( Any, {x | x> 0}) YES \x -> x 2 Any YES BAD 2 Any -> Any NO BAD 2 (Any, Any) NO Inlining may help, but breaks down when function definition is big or recursive

All Contracts are Inhabited e 2 {x | p}, e " or (e is crash-free and p[e/x] ! * {BAD, False} e 2 x:t 1 ! t 2, 8 e 1 2 t 1. (e e 1 ) 2 t 2 [e 1 /x] e 2 (t 1, t 2 ), e " or (e ! * (e 1,e 2 ) and e 1 2 t 1 and e 2 2 t 2 ) e 2 Any, True YES or NO? \x-> BAD 2 Any -> Any YES \x-> BAD 2 {x | True} -> Any YES \x-> BAD 2 {x | False} -> {r | True} NO Blume&McAllester[JFP’06] say YES

28 What to Check? Does function f satisfy its contract t (written f 2 t)? At the definition of each function f, Check f 2 t assuming all functions called in f satisfy their contracts. Goal: main 2 {x | True} ( main is crash-free, hence the program cannot crash)

How to Check? Define e 2 t Construct e B t (e “ensures” t) Grand Theorem e 2 t, e B t is crash-free (related to Blume&McAllester:JFP’06) some e’ Simplify (e B t) If e’ is syntactically safe, then Done! Part I Part II

30 What we can’t do? g1, g2 2 Ok -> Ok g1 x = case (prime x > square x) of True -> x False -> error “urk” g2 xs ys = case (rev (xs ++ ys) == rev ys ++ rev xs) of True -> xs False -> error “urk” Hence, three possible outcomes: (1) Definitely Safe (no crash, but may loop) (2) Definite Bug (definitely crashes) (3) Possible Bug Crash!

31 Wrappers B and C ( B pronounced ensures C pronounced requires) e B {x | p} = case p[e/x] of True -> e False -> BAD e B x:t 1 ! t 2 =  v. (e (v C t 1 )) B t 2 [v C t 1 /x] e B (t 1, t 2 ) = case e of (e 1, e 2 ) -> (e 1 B t 1, e 2 B t 2 ) e B Any = UNR related to [Findler:ICFP02,Blume:JFP06,Hinze:FLOPS06]

32 Wrappers B and C ( B pronounced ensures C pronounced requires) e C {x | p} = case p[e/x] of True -> e False -> UNR e C x:t 1 ! t 2 =  v. (e (v B t 1 )) C t 2 [v B t 1 /x] e C (t 1, t 2 ) = case e of (e 1, e 2 ) -> (e 1 C t 1, e 2 C t 2 ) e C Any = BAD related to [Findler:ICFP02,Blume:JFP06,Hinze:FLOPS06]

Simple Example f 2 {x | x > 0} -> {r | r > 0} f x = case x > 0 of True -> x + 1 False -> BAD f B {x | x > 0} -> {r | r > 0} = \v -> ((f (v C {x | x > 0})) B {r | r > 0}) = \v -> ((f (case v > 0 of True -> v False -> UNR)) B {r | r > 0}) = … 33

Higher-Order Function f1 B ({x | True} -> {y | y >= 0}) -> {r | r >= 0} = … B C B = v 1. case (v 1 1) >= 0 of True -> case (v 1 1) - 1 >= 0 of True -> (v 1 1) -1 False -> BAD False -> UNR f1 :: (Int -> Int) -> Int f1 2 ({x | True} -> {y | y >= 0}) -> {r | r >= 0} f1 g = (g 1) - 1 f2:: {r | True} f2 = f1 (\x -> x – 1)

e B {x | p} = case p[e/x] of True -> e False -> BAD loop 2 {x | False} loop B {x | False} = case False of {True -> loop; False -> BAD} = BAD, which is not crash-free BAD 2 Ok -> Any BAD B Ok -> Any = \v -> ((BAD (v C Ok)) B Any = \v -> UNR, which is crash-free Grand Theorem e 2 t, e B t is crash-free 

e B {x | p} = e `seq` case p[e/x] of True -> e False -> BAD loop 2 {x | False} loop B {x | False} = loop `seq` case False of {…} = loop, which is crash-free BAD 2 Ok -> Any BAD B Ok -> Any = BAD `seq` \v -> ((BAD (v C Ok)) B Any = BAD, which is not crash-free Grand Theorem e 2 t, e B t is crash-free e_1 `seq` e_2 = case e_1 of {DEFAULT -> e_2}

Contracts that Diverge \x->BAD 2 {x | loop} ? NO But \x->BAD B {x | loop} = \x->BAD `seq` case loop of True -> \x -> BAD False -> BAD e B {x | p} = e `seq` case fin p[e/x] of True -> e False -> BAD fin converts divergence to True crash-free

Contracts that Crash  … much trickier ( ) ) does not hold, ( ( ) still holds  Open Problem Suppose fin converts BAD to False Not sure if Grand Theorem holds because NO proof, and NO counter example either. 38 Grand Theorem e 2 t, e B t is crash-free

Well-formed Contracts Grand Theorem e 2 t, e B t is crash-free Well-formed t t is Well-formed (WF) iff t = {x | p} and p is crash-free or t = x:t 1 ! t 2 and t 1 is WF and 8 e 1 2 t 1, t 2 [e 1 /x ] is WF or t = ( t 1, t 2 ) and both t 1 and t 2 are WF or t = Any

40 Properties of B and C Key Lemma: For all closed, crash-free e, and closed t, (e C t) 2 t Projections: (related to Findler&Blume:FLOPS’06) For all e and t, if e 2 t, then (a) e ¹ e B t (b) e C t ¹ e Definition (Crashes-More-Often): e 1 ¹ e 2 iff for all C, ` C[[e i ]] :: () for i=1,2 and C[[e 2 ]] ! * BAD ) C[[e 1 ]] ! * BAD

41 More Lemmas Lemma [Monotonicity of Satisfaction ]: If e 1 2 t and e 1 ¹ e 2, then e 2 2 t Lemma [Congruence of ¹ ]: e 1 ¹ e 2 ) 8 C. C[[e 1 ]] ¹ C[[e 2 ]] Lemma [Idempotence of Projection]: 8 e, t. e B t B t ≡ e B t 8 e, t. e C t C t ≡ e C t Lemma [A Projection Pair]: 8 e, t. e B t C t ¹ e Lemma [A Closure Pair]: 8 e, t. e ¹ e C t B t

42 How to Check? Define e 2 t Construct e B t (e “ensures” t) Grand Theorem e 2 t, e B t is crash-free (related to Blume&McAllester:ICFP’04) Normal form e’ Simplify (e B t) If e’ is syntactically safe, then Done! Part I Part II

43 Simplification Rules

44 Arithmetic via External Theorem Prover foo :: Int -> Int -> Int foo 2 {i | True} -> { i > j } -> {r | True} foo C t foo = \i-> \j -> case i > j of False -> BAD “foo” True -> … goo i = foo (i+8) i goo B t goo = \i -> case (i+8 > i) of False -> BAD “foo” True -> … >>ThmProver i+8>i >>Valid! case i > j of True -> case j < 0 of False -> case i > 0 of False -> BAD “f” >>ThmProver push(i>j) push(not (j<0)) (i>0) >>Valid!

45 Counter-Example Guided Unrolling sumT :: T -> Int sumT 2 {x | noT1 x } -> {r | True} sumT (T2 a) = a sumT (T3 t1 t2) = sumT t1 + sumT t2 After simplifying (sumT B t sumT ), we may have: case (noT1 x) of True -> case x of T1 a -> BAD T2 a -> a T3 t1 t2 -> case (noT1 t1) of False -> BAD True -> case (noT1 t2) of False -> BAD True -> sumT t1 + sumT t2

46 Step 1: Program Slicing – Focus on the BAD Paths case (noT1 x) of True -> case x of T1 a -> BAD T3 t1 t2 -> case (noT1 t1) of False -> BAD True -> case (noT1 t2) of False -> BAD

47 Step 2: Unrolling case (case x of T1 a -> False T2 a -> True T3 t1 t2 -> noT1 t1 && noT1 t2) of True -> case x of T1 a -> BAD T3 t1 t2 -> case (noT1 t1) of False -> BAD True -> case (noT1 t2) of False -> BAD

48 Counter-Example Guided Unrolling – The Algorithm

49 Tracing (Achieve the same goal as [Meunier, Findler, Felleisen:POPL06] g 2 t g g = … f 2 t f f = …g … f B t f = …g C t g … (\g ! …g …) B t g ! t f Inside “g” lc (g C t g ) case fin p[e/x] of True -> e False -> BAD “f”

50 Counter-Example Generation f3 B Ok = \xs -> \z -> case xs of [] -> 0 (x:y) -> case x > z of True -> Inside “f2” (Inside “f1” (BAD “f1”)) False -> … Warning : f3 (x:y) z where x>z calls f2 which calls f1 which may fail f1’s precondition! f3 [] z = 0 f3 (x:xs) z = case x > z of True -> f2 x z False ->... f1 2 x:Ok -> { x Ok f2 x z = 1 + f1 x z

51 Contributions  Automatic static contract checking instead of dynamic contract checking.  Contracts are written in Haskell itself Allow pre/post specification for higher-order function’s parameter through contracts. Reduce false alarms caused by Laziness. Allow user-defined data constructors to be used to define contracts Specifications are more type-like, so we can define contract synonym.  We develop a concise notation ( B and C ) for contract checking, which enjoys many properties. We give a new and simpler proof of the soundness and completeness of dynamic contract checking, this proof is much trickier than it looks.  We implement the idea in GHC Accept full Haskell ( Support separate compilation as the verification is modular. Can check functions without contract through CEG unrolling.

52 Conclusion Contract Haskell Program Glasgow Haskell Compiler (GHC) Where the bug is Why it is a bug

Recursion f B t =\f->f B t->t = … =(… (f C t)…) B t Suppose t = t1 -> t_2 f B t1 -> t2 = \f->f B (t1 -> t2) -> (t1 -> t2) = … =(… (f C t1 -> t2)…) B t1 -> t2 =\v2.((…(\v1.((f (v1 B t1)) C t2)) (v2 C t1) …) B t2) 53

Simple Example head 2 {xs | not (null xs)} -> Ok head [] = BAD head (x:xs’) = x head B {xs | not (null xs)} -> Ok = \v -> (head (v C {xs | not (null xs)}) B Ok) = ( because e B Ok = e) \v -> (head (v C {xs | not (null xs)}) = \v -> (head (case not (null v) of True -> v False -> UNR)) = ( inline not, null, and head) \v -> case v of [] -> UNR (x:xs) -> x 54